前言
本篇文件主要是把最近试用的shiro的过程记录一下
正文
在shirt中,有很多filter,
FormAuthenticationFilter
就是其中之一。这个Filter不能算是最简单(内部有一些隐含处理),但算是一个标准Filter。使用这个Filter时候的注意点说一下:
shiro.ini
在这个文件中,在配置验证时候,只需要配置以下内容:
[main]
authc.loginUrl=/login
authc.usernameParam=username
authc.passwordParam=password
authc.successUrl=/
不需要配置
authc = org.apache.shiro.web.filter.authc.FormAuthenticationFilter
,因为默认的就是
FormAuthenticationFilter
。
login方法
在写login方法,要留意两点:
1. 不用像以往的方式去写,例如:
登录成功后,跳到哪个画面;登录不成功,跳到哪个画面
。因为如果登录成功后,会跳到上面ini文件中,
successUrl
指定的地址;如果是访问别的路径时,自动跳转到login画面的话,登录成功后会跳转到之前的那个路径。
2. login方法中,不用像下面那样使用shiro。
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<SecurityManager> factory =
new IniSecurityManagerFactory(configFile);
//2、得到SecurityManager实例 并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
subject.login(token);
上面的代码,在
FormAuthenticationFilter
内部都已经做完了。如果进入到后台的login方法的话,说明验证失败,我们只需要在login方法中写上验证失败的逻辑就好,如下:
@Action("post:/login")
public View loginSubmit(Param param) {
String errorClassName = (String) ServletHelper.getRequestAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
if(UnknownAccountException.class.getName().equals(errorClassName)) {
ServletHelper.setRequestAttribute("error", "用户名/密码错误");
} else if(IncorrectCredentialsException.class.getName().equals(errorClassName)) {
ServletHelper.setRequestAttribute("error", "用户名/密码错误");
} else if(errorClassName != null) {
ServletHelper.setRequestAttribute("error", "未知错误:" + errorClassName);
}
// 登录失败后,跳回到login画面,让用户再次登录
return new View("login);
}
具体代码如下:
Controller:
package org.smart4j.chapter3.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smart4j.framework.annotation.Action;
import org.smart4j.framework.annotation.Controller;
import org.smart4j.framework.bean.Param;
import org.smart4j.framework.bean.View;
import org.smart4j.framework.helper.ServletHelper;
/**
* Created by shijiapeng on 16/12/20.
*/
@Controller
public class SystemController {
private static final Logger LOGGER = LoggerFactory.getLogger(SystemController.class);
@Action("get:/")
public View index() {
return new View("index.jsp");
}
@Action("get:/login")
public View login() {
return new View("login.jsp");
}
@Action("post:/login")
public View loginSubmit(Param param) {
String errorClassName = (String) ServletHelper.getRequestAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
if(UnknownAccountException.class.getName().equals(errorClassName)) {
ServletHelper.setRequestAttribute("error", "用户名/密码错误");
} else if(IncorrectCredentialsException.class.getName().equals(errorClassName)) {
ServletHelper.setRequestAttribute("error", "用户名/密码错误");
} else if(errorClassName != null) {
ServletHelper.setRequestAttribute("error", "未知错误:" + errorClassName);
}
return new View("/customer_edit?id=1");
}
@Action("get:/logout")
public View logout() {
SecurityUtils.getSubject().logout();
return new View("/login");
}
}
shirt.ini:
[main]
authc.loginUrl=/login
authc.usernameParam=username
authc.passwordParam=password
authc.successUrl=/customer
#authc = org.apache.shiro.web.filter.authc.FormAuthenticationFilter
#authc = org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter
ds=org.apache.commons.dbcp2.BasicDataSource
ds.driverClassName=com.mysql.jdbc.Driver
ds.url=jdbc:mysql://localhost:3306/Test
ds.username=root
ds.password=root
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$ds
jdbcRealm.authenticationQuery=SELECT password FROM user WHERE username = ?
jdbcRealm.userRolesQuery=SELECT role_name FROM user u, role r, user_role ur WHERE u.id = ur.user_id AND r.id = ur.role_id AND u.username = ?
jdbcRealm.permissionsQuery=SELECT permission_name FROM permission p, role r, role_permission rp WHERE r.id = rp.role_id AND rp.permission_id = p.id AND r.role_name = ?
jdbcRealm.permissionsLookupEnabled=true
securityManager.realms=$jdbcRealm
[urls]
/*=authc
login.jsp:
<%@ page pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<c:set var="BASE" value="${pageContext.request.contextPath}"/>
<html>
<head>
<title>登录</title>
</head>
<body>
<h1>登录</h1>
<shiro:guest>
<form action="${BASE}/login" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td colspan="2">
<button type="submit">登录</button>
</td>
</tr>
</table>
</form>
</shiro:guest>
<shiro:user>
shir:user
<c:redirect url="${BASE}/customer_edit?id=2"/>
</shiro:user>
</body>
</html>