Webアプリケーションへのインテグレーション
前々回に引き続いて、
ShiroとWebアプリとの連携はServletフィルタの機構を利用して行います。Shiroにはjavax.
web.
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
<init-param>
<param-name>configPath</param-name>
<param-value>/WEB-INF/shiro.ini</param-value>
</init-param>
</filter>
その他に、
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
<init-param>
<param-name>config</param-name>
<param-value>
[main]
……
[urls]
/index.jsp = anon
……
[users]
gihyo = gihyopass
</param-value>
</init-param>
</filter>
INIファイルの書き方は、
認証フィルタには下表のようなものがあります。その他に、
フィルタ名 | 内容 | 使用されるクラス名 |
---|---|---|
anon | 認証を行わない。 | AnonymousFilter |
authc | フォームを使ったログイン認証を行う。認証されていないアクセスはログインページへリダイレクトする | FormAuthenticationFilter |
authcBasic | HTTPのBasic認証を行う。 | BasicHttpAuthenticationFilter |
perms | ログイン中のユーザからのコンテンツごとのアクセス権を制御する | PermissionsAuthorizationFilter |
port | 特定のポートへのリクエストのみ許可する。 | PortFilter |
rest | HTTPリクエスト別にアクセス制御を行う。RESTサービスなどの実装に利用する | HttpMethodPermissionFilter |
roles | ロール別のアクセス権を制御する | RolesAuthorizationFilter |
ssl | SSLによる認証を行う | SslFilter |
user | 既知のユーザ | UserFilter |
認証フィルタもServletフィルタの一種です。たとえば
以下に、
;[main]
;securityManager.sessionManager.sessionValidationSchedulerEnabled = false
;sessionListener = jp.gihyo.toolbox.shiro.MySessionListener
;securityManager.sessionManager.sessionListeners = $sessionListener
[filters]
authc.loginUrl = /login.jsp
[urls]
/index.jsp = anon
/login.jsp = anon
/user/** = authc
[users]
gihyo = gihyopass
ログイン処理を行うプログラムの作成
続いてログインページやServletのプログラムを作っていきましょう。まず、
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Shiroサンプル - ログインページ</title>
</head>
<body>
<h1>ログインページ</h1>
<form action="Login" method="POST">
ユーザ名: <input type="text" name="username"/> <br/>
パスワード: <input type="password" name="password"/> <br/>
<input type="submit" name="loginButton" value="ログイン"/>
</form>
</body>
</html>
ログインページからの入力を処理するServletはLogin.
public class Login extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String url = "/login.jsp"; // リダイレクト先のURL
// ユーザ名とパスワードを取得
String username = request.getParameter("username");
String password = request.getParameter("password");
// Tokenを作成
UsernamePasswordToken token =
new UsernamePasswordToken(username, password);
try {
// Subjectを取得
Subject subject = SecurityUtils.getSubject();
// ログイン
subject.login(token);
token.clear();
url = "/user/content.jsp";
} catch (UnknownAccountException ex) {
ex.printStackTrace();
} catch (IncorrectCredentialsException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
// リダイレクト
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher(url);
dispatcher.forward(request, response);
}
}
ここでは、
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Shiroサンプル - コンテンツ</title>
</head>
<body>
<p>ここは保護されたページです。</p>
<h1>コンテンツページ</h1>
<p><a href="<c:url value='/Logout' />">ログアウト</a></p>
</body>
</html>
ログアウトを行うプログラムはLogout.
public class Logout extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String url = "/login.jsp"; // リダイレクト先のURL
// Subjectを取得
Subject subject = SecurityUtils.getSubject();
if (subject != null) {
// ログアウト
subject.logout();
}
HttpSession session = request.getSession(false);
if( session != null ) {
// セッションの終了
session.invalidate();
}
// リダイレクト
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher(url);
dispatcher.forward(request, response);
}
}
web.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
<init-param>
<param-name>configPath</param-name>
<param-value>/WEB-INF/shiro.ini</param-value>
</init-param>
</filter>
<servlet>
<servlet-name>Login</servlet-name>
<servlet-class>jp.gihyo.toolbox.shiro.Login</servlet-class>
</servlet>
<servlet>
<servlet-name>Logout</servlet-name>
<servlet-class>jp.gihyo.toolbox.shiro.Logout</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Login</servlet-name>
<url-pattern>/Login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Logout</servlet-name>
<url-pattern>/Logout</url-pattern>
</servlet-mapping>
</web-app>
以上で完成です。Webサーバにデプロイしてブラウザから/user/

ログインに成功すると、

カスタムタグライブラリを使う
ShiroにはWebアプリケーションで使うためのJSP/
たとえば、
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Shiroサンプル - </title>
</head>
<body>
<shiro:user>
<p>こんにちは、<shiro:principal/> さん。</br>
<shiro:principal/> さんではない場合は
<a href="<c:url value='/Logout' />">ここ</a>をクリックしてログアウトしてください。</p>
</shiro:user>
<shiro:guest>
<p><a href="<c:url value='/Logout' />">このページ</a>からログインしてください。</p>
</shiro:guest>
</body>
</html>
認証が行われていないユーザに対しては、


Webアプリケーションにユーザ認証は不可欠ですが、