1、什么是Apache Shiro
Apache Shiro,Java的一个开源安全框架,类似的还有Spring Security,用于简洁地处理身份验证,授权,企业多个系统会话管理,加密服务等。
2、三大主要组件
Subject:代表了当前用户,与应用代码直接交互的shiro对外API;
SecurityManager:安全管理器,所有与安全有关的操作都会与SecurityManager交互,管理这所有的Subject,负责与其他shiro组件进行交互,是shiro的核心组件
Realm:域,Shiro从realm中获取安全数据(用户/角色/权限),即安全数据源,由开发人员自己注入。
3、其他组件
在shiro的用户权限认证过程中其通过两个方法来实现:
1、Authentication:是验证用户身份的过程。
2、Authorization:是授权访问控制,用于对用户进行的操作进行人证授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。
4、Shiro标签
<shiro:guest> 验证未登录用户
<shiro:user>验证已登陆用户
<shiro:authenticated>已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。
<shiro:notAuthenticated>未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。
<shiro:principal/>输出当前用户信息,通常为登录帐号信息。Hello, <shiro:principal/>, how are you today?
<shiro:hasRole name="administrator"> 验证当前用户是否属于该角色。
<shiro:lacksRole name="administrator"> 与hasRole标签逻辑相反,当用户不属于该角色时验证通过。
<shiro:hasAnyRoles name="developer, project manager, administrator">验证当前用户是否属于以下任意一个角色
<shiro:hasPermission name="user:create">验证当前用户是否拥有指定权限。
<shiro:hasPermission name="user:create"> 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。
注意:会进入授权方法一共有三种情况!
1、subject.hasRole(“admin”) 或 subject.isPermitted(“admin”):自己去调用这个是否有什么角色或者是否有什么权限的时候;
2、@RequiresRoles("admin") :在方法上加注解的时候;
3、[@shiro.hasPermission name = "admin"][/@shiro.hasPermission]:在页面上加shiro标签的时候,即进这个页面的时候扫描到有这个标签的时候。
5.配置(这里主要展示如何配置多个realm,支持用户名密码登陆和手机验证码登陆)
pom.xml
<!-- shiro start -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-aspectj</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
</dependency>
<!-- shiro end -->
web.xml
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd" default-lazy-init="true">
<!-- shiro集群改造,参考:http://git.oschina.net/zhmlvft/spring_shiro_redis http://git.oschina.net/1231/spinach -->
<bean id="modelAuthricator" class="com.jusfoun.socialgrid.shiro.DefaultModularRealm">
<property name="definedRealms">
<map>
<entry key="shiroDbRealm" value-ref="shiroDbRealm" />
<entry key="shiroVertifyRealm" value-ref="shiroVertifyRealm" />
</map>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realms">
<list>
<ref bean="shiroDbRealm" />
<ref bean="shiroVertifyRealm" />
</list>
</property>
<property name="authenticator" ref="modelAuthricator"/>
<property name="sessionManager" ref="sessionManager" />
<property name="cacheManager" ref="redisCacheManager" />
</bean>
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionDAO" ref="sessionDAO" />
<property name="sessionIdCookieEnabled" value="true" />
<property name="sessionIdCookie" ref="sessionIdCookie" />
<property name="deleteInvalidSessions" value="true" />
<property name="sessionValidationSchedulerEnabled" value="true" />
</bean>
<bean id="redisCacheManager" class="com.itmuch.core.shiro.RedisCacheManager">
<property name="redisManager" ref="redisManager" />
</bean>
<bean id="redisManager" class="com.itmuch.core.shiro.RedisManager">
<property name="expire" value="${redis.expireTime}" />
<property name="host" value="${redis.host}" />
<property name="password" value="${redis.pass}" />
<property name="port" value="${redis.port}" />
<property name="timeout" value="${redis.maxWait}" />
</bean>
<!-- session 保存到cookie,关闭浏览器下次可以直接登录认证,当maxAge为-1不会写cookie。 -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="sid" />
<property name="httpOnly" value="true" />
<!-- 浏览器关闭session失效,不计入cookie -->
<property name="maxAge" value="-1" />
</bean>
<bean id="shiroDbRealm" class="com.jusfoun.socialgrid.shiro.ShiroDbRealm">
<property name="credentialsMatcher" ref="credentialsMatcher"></property>
</bean>
<bean id="shiroVertifyRealm" class="com.jusfoun.socialgrid.shiro.ShiroVertifyRealm">
</bean>
<!-- 自定义身份验证器,用于限制用户尝试次数,防止暴力登陆 -->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5"></property>
<!-- true means hex encoded, false means base64 encoded -->
<property name="storedCredentialsHexEncoded" value="true" />
<!-- <property name="hashIterations" value="1" /> -->
</bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<!-- <property name="unauthorizedUrl" value="${adminPath}" /> -->
<property name="successUrl" value="/" />
<property name="filters">
<map>
<entry key="authc" value-ref="authcFilter" />
</map>
</property>
<property name="filterChainDefinitions">
<value>
/*.json = anon
/common/upload = anon
/static/** = anon
/druid/* = perms[sys:datasource:view]
/vertificate/sendDxCode = anon
/sendDxCode = anon
/login = anon
/logout = logout
/getVerifyCode = anon
/loginByVertifyCode = anon
/** = user
</value>
</property>
</bean>
<bean id="authcFilter" class="com.jusfoun.socialgrid.shiro.MyFormAuthenticationFilter"></bean>
<!-- 自定义shiro的sessionDao,把session写入redis -->
<bean id="sessionDAO" class="com.itmuch.core.shiro.RedisSessionDao">
<constructor-arg ref="redisTemplate" />
<constructor-arg value="${redis.expireTime}" />
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans>
自定义异常类CaptchaException
package com.jusfoun.socialgrid.shiro;
import org.apache.shiro.authc.AuthenticationException;
/**
* 验证码异常类
* @author user
*
*/
public class CaptchaException extends AuthenticationException{
/**
*
*/
private static final long serialVersionUID = 1L;
public CaptchaException() {
super();
}
public CaptchaException(String message, Throwable cause) {
super(message, cause);
}
public CaptchaException(String message) {
super(message);
}
public CaptchaException(Throwable cause) {
super(cause);
}
}
DefaultModularRealm类
package com.jusfoun.socialgrid.shiro;
import java.util.Collection;
import java.util.Map;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.util.CollectionUtils;
public class DefaultModularRealm extends ModularRealmAuthenticator {
private Map<String, Object> definedRealms;
/**
* 多个realm实现
*/
@Override
protected AuthenticationInfo doMultiRealmAuthentication(
Collection<Realm> realms, AuthenticationToken token) {
return super.doMultiRealmAuthentication(realms, token);
}
/**
* 调用单个realm执行操作
*/
@Override
protected AuthenticationInfo doSingleRealmAuthentication(Realm realm,
AuthenticationToken token) {
// 如果该realms不支持(不能验证)当前token
if (!realm.supports(token)) {
throw new ShiroException("token错误!");
}
AuthenticationInfo info = null;
try {
info = realm.getAuthenticationInfo(token);
if (info == null) {
throw new ShiroException("token不存在!");
}
} catch (Exception e) {
throw new ShiroException("用户名或者密码错误!");
}
return info;
}
/**
* 判断登录类型执行操作
*/
@Override
protected AuthenticationInfo doAuthenticate(
AuthenticationToken authenticationToken)
throws AuthenticationException {
this.assertRealmsConfigured();
Realm realm = null;
if(authenticationToken instanceof UsernamePasswordToken){
realm = (Realm) this.definedRealms.get("shiroDbRealm");
}
if(authenticationToken instanceof UsernamePasswordCaptchaToken){
realm = (Realm) this.definedRealms.get("shiroVertifyRealm");
}
if (realm == null) {
return null;
}
return this.doSingleRealmAuthentication(realm, authenticationToken);
}
/**
* 判断realm是否为空
*/
@Override
protected void assertRealmsConfigured() throws IllegalStateException {
this.definedRealms = this.getDefinedRealms();
if (CollectionUtils.isEmpty(this.definedRealms)) {
throw new ShiroException("值传递错误!");
}
}
public Map<String, Object> getDefinedRealms() {
return this.definedRealms;
}
public void setDefinedRealms(Map<String, Object> definedRealms) {
this.definedRealms = definedRealms;
}
}
MyFormAuthenticationFilter类
package com.jusfoun.socialgrid.shiro;
import java.io.PrintWriter;
import java.util.Date;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itmuch.core.constants.CodeConstant;
import com.itmuch.core.util.ErrorMsgUtil;
import com.itmuch.core.web.converter.Result;
import com.jusfoun.socialgrid.admin.service.UserService;
import com.jusfoun.socialgrid.util.common.IPUtil;
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(MyFormAuthenticationFilter.class);
public static final String DEFAULT_CAPTCHA_PARAM = "captcha";
private String captchaParam = DEFAULT_CAPTCHA_PARAM;
public String getCaptchaParam() {
return captchaParam;
}
protected String getCaptcha(ServletRequest request) {
return WebUtils.getCleanParam(request, getCaptchaParam());
}
@Resource
private UserService userService;
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
String principal = (String) subject.getPrincipal();
com.jusfoun.socialgrid.admin.domain.User currUser = this.userService.selectByUsername(principal);
if (currUser != null) {
// 最后一次登陆ip 与时间等等
String ip = IPUtil.getIpAddr((HttpServletRequest) request);
LOGGER.info("用户:{}登陆成功, IP:{}, 当前时间:{}.", currUser.getUsername(), ip, new Date());
}
return super.onLoginSuccess(token, subject, request, response);
}
/**
* 适应ajax情况下用户访问不允许访问的页面时的情况
* 参考: http://my.oschina.net/WMSstudio/blog/162594
* 参考: http://ketayao.com/view/9
* 参考: http://blog.youkuaiyun.com/shadowsick/article/details/39021265
*/
@Override
protected boolean onAccessDenied(ServletRequest req, ServletResponse response) throws Exception {
HttpServletRequest request = (HttpServletRequest) req;
String accept = request.getHeader("accept");
String header = request.getHeader("X-Requested-With");
// ajax 请求
if (((accept != null) && (accept.indexOf("application/json") > -1)) || ((header != null) && (header.indexOf("XMLHttpRequest") > -1))) {
if (!this.isLoginRequest(req, response)) {
Result result = ErrorMsgUtil.error("用户未登录", "用户未登录, 或用户登录已超时, 请重新登录", CodeConstant.UNKNOW_ERROR_CODE);
ObjectMapper om = new ObjectMapper();
om.setSerializationInclusion(Include.NON_NULL);
String writeValueAsString = om.writeValueAsString(result);
response.setContentType("text/json; charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.println(writeValueAsString);
out.flush();
out.close();
return false;
} else {
return true;
}
} else {
return super.onAccessDenied(request, response);
}
}
}
ShiroDbRealm类,第一个realm用于用户名密码登陆;这里变态的要求三个用户表,用时按照自己的需求修改即可
package com.jusfoun.socialgrid.shiro;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.itmuch.core.constants.SessionConstants;
import com.itmuch.core.util.SubjectUtil;
import com.jusfoun.socialgrid.admin.domain.CommissionUser;
import com.jusfoun.socialgrid.admin.domain.CompanyUser;
import com.jusfoun.socialgrid.admin.domain.User;
import com.jusfoun.socialgrid.admin.persistence.CommissionUserMapper;
import com.jusfoun.socialgrid.admin.persistence.CompanyUserMapper;
import com.jusfoun.socialgrid.admin.service.RoleService;
import com.jusfoun.socialgrid.admin.service.UserService;
import com.jusfoun.socialgrid.gridManager.domain.GridManager;
import com.jusfoun.socialgrid.gridManager.persistence.GridManagerMapper;
public class ShiroDbRealm extends AuthorizingRealm {
@Resource
private UserService userService;
@Resource
private RoleService roleService;
@Autowired
public GridManagerMapper gridMp;
@Autowired
public CommissionUserMapper commMp;
@Autowired
public CompanyUserMapper comUserMp;
private static final Logger LOGGER = LoggerFactory.getLogger(ShiroDbRealm.class);
/**
* 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();
// 1. 通过用户id,查询用户具有的角色(查询sys_admin_role)
Long id = SubjectUtil.getUser().getId();
// 如果是超级管理员, 则拥有所有权限, 不受角色约束
List<String> permissions = null;
if (1L == id) {
permissions = this.userService.selectAllPermissions();
}
// 并非超管
else {
List<Long> roleIds = this.userService.selectRoleIdListByUserId(id);
if ((roleIds != null) && !roleIds.isEmpty()) {
// 2. 通过角色id, 查询角色具有的权限
permissions = this.userService.selectPermissionsByRoleIds(roleIds);
}
}
if ((permissions != null) && !permissions.isEmpty()) {
auth.addStringPermissions(permissions);
return auth;
}
return null;
}
/**
* 认证回调函数,登录时调用.
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String userName = token.getUsername();
LOGGER.info("用户:{}尝试登陆.", userName);
String roleId = (String)SecurityUtils.getSubject().getSession().getAttribute("role_id");
User user = null;
if("1".equals(roleId)){
user = this.userService.selectByUsername(userName);
}else if("2".equals(roleId)){
//委办局人员登录
List<CommissionUser> list = commMp.selectCommByName(userName);
if(list!=null&&list.size()!=0){
CommissionUser commUser = list.get(0);
user = new User();
user.setUsername(commUser.getUsername());
user.setMobile(commUser.getMobile());
user.setId(commUser.getId());
user.setPassword(commUser.getPassword());
user.setSalt(commUser.getSalt());
}
}else if("3".equals(roleId)||"4".equals(roleId)){
//网格长和网格员登录
List<GridManager> list = gridMp.selectGridMgrByName(userName);
if(list!=null&&list.size()!=0){
GridManager gridMgr = list.get(0);
user = new User();
user.setUsername(gridMgr.getUsername());
user.setMobile(gridMgr.getMobile());
user.setId(gridMgr.getId());
user.setPassword(gridMgr.getPassword());
user.setSalt(gridMgr.getSalt());
}
}else if("5".equals(roleId)){
//企业用户登录
CompanyUser comUser = comUserMp.selectByUsername(userName);
if(comUser!=null){
user = new User();
user.setUsername(comUser.getUsername());
user.setMobile(comUser.getMobile());
user.setId(comUser.getId());
user.setPassword(comUser.getPassword());
user.setSalt(comUser.getSalt());
}
}
// User user = this.userService.selectByUsername(username);
if (user != null) {
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, user.getPassword(),ByteSource.Util.bytes(user.getSalt()),this.getName());
com.itmuch.core.util.User currUser = new com.itmuch.core.util.User();
currUser.setUsername(user.getUsername());
currUser.setMobile(user.getMobile());
currUser.setId(user.getId());
this.setSession(SessionConstants.USER, currUser);
return info;
} else {
return null;
}
}
/**
* 设置session
* @param key key
* @param value value
*/
private void setSession(Object key, Object value) {
Subject currentUser = SecurityUtils.getSubject();
if (null != currentUser) {
Session session = currentUser.getSession();
if (null != session) {
session.setAttribute(key, value);
}
}
}
/**
* 参考文档: http://www.tuicool.com/articles/rEvqym
* 参考文档: http://sishuok.com/forum/blogPost/list/7461.html
* 参考文档: http://m.blog.youkuaiyun.com/blog/LHacker/19340757
*/
public void clearCache() {
Subject subject = SecurityUtils.getSubject();
super.clearCachedAuthorizationInfo(subject.getPrincipals());
}
/**
* 通过身份信息, 清空该用户的权限缓存
* 参考: http://m.blog.youkuaiyun.com/blog/LHacker/19340757
* @param principle 身份信息
*/
public void clearAuthorizationCacheByPrinciple(String principle) {
String cacheName = this.getAuthorizationCacheName();
Cache<Object, Object> cache = this.getCacheManager().getCache(cacheName);
Set<Object> keys = cache.keys();
if (CollectionUtils.isNotEmpty(keys)) {
for (Object key : keys) {
SimplePrincipalCollection spc = (SimplePrincipalCollection) key;
if (principle.equals(spc.toString())) {
cache.remove(key);
break;
}
}
}
}
}
ShiroVertifyRealm类
package com.jusfoun.socialgrid.shiro;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.itmuch.core.constants.SessionConstants;
import com.itmuch.core.util.SubjectUtil;
import com.jusfoun.socialgrid.admin.domain.CommissionUser;
import com.jusfoun.socialgrid.admin.domain.User;
import com.jusfoun.socialgrid.admin.persistence.CommissionUserMapper;
import com.jusfoun.socialgrid.admin.service.RoleService;
import com.jusfoun.socialgrid.admin.service.UserService;
import com.jusfoun.socialgrid.gridManager.domain.GridManager;
import com.jusfoun.socialgrid.gridManager.persistence.GridManagerMapper;
public class ShiroVertifyRealm extends AuthorizingRealm{
final static Logger LOGGER = LoggerFactory.getLogger(ShiroVertifyRealm.class);
@Resource
private UserService userService;
@Resource
private RoleService roleService;
@Autowired
public GridManagerMapper gridMp;
@Autowired
public CommissionUserMapper commMp;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();
// 1. 通过用户id,查询用户具有的角色(查询sys_admin_role)
Long id = SubjectUtil.getUser().getId();
// 如果是超级管理员, 则拥有所有权限, 不受角色约束
List<String> permissions = null;
if (1L == id) {
permissions = this.userService.selectAllPermissions();
}
// 并非超管
else {
List<Long> roleIds = this.userService.selectRoleIdListByUserId(id);
if ((roleIds != null) && !roleIds.isEmpty()) {
// 2. 通过角色id, 查询角色具有的权限
permissions = this.userService.selectPermissionsByRoleIds(roleIds);
}
}
if ((permissions != null) && !permissions.isEmpty()) {
auth.addStringPermissions(permissions);
return auth;
}
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordCaptchaToken token = (UsernamePasswordCaptchaToken)authenticationToken;
String userName = token.getUsername();
LOGGER.info("用户:{}尝试登陆.", userName);
String roleId = (String)SecurityUtils.getSubject().getSession().getAttribute("role_id");
// 增加判断验证码逻辑
String captcha = token.getCaptcha();
String verCode = (String)SecurityUtils.getSubject().getSession().getAttribute("loginCode");
if (null == captcha || !captcha.equals(verCode)) {
throw new CaptchaException("验证码错误");
}
User user = null;
if("1".equals(roleId)){
user = this.userService.selectByUsername(userName);
}else if("2".equals(roleId)){
//委办局人员登录
List<CommissionUser> list = commMp.selectCommByName(userName);
if(list!=null&&list.size()!=0){
CommissionUser commUser = list.get(0);
user = new User();
user.setUsername(commUser.getUsername());
user.setMobile(commUser.getMobile());
user.setId(commUser.getId());
user.setPassword(commUser.getPassword());
user.setSalt(commUser.getSalt());
}
}else if("3".equals(roleId)||"4".equals(roleId)){
//网格长和网格员登录
List<GridManager> list = gridMp.selectGridMgrByName(userName);
if(list!=null&&list.size()!=0){
GridManager gridMgr = list.get(0);
user = new User();
user.setUsername(gridMgr.getUsername());
user.setMobile(gridMgr.getMobile());
user.setId(gridMgr.getId());
user.setPassword(gridMgr.getPassword());
user.setSalt(gridMgr.getSalt());
}
}
// User user = this.userService.selectByUsername(userName);
if (user != null) {
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, user.getPassword(), ByteSource.Util.bytes(user.getSalt()),
this.getName());
com.itmuch.core.util.User currUser = new com.itmuch.core.util.User();
currUser.setUsername(user.getUsername());
currUser.setMobile(user.getMobile());
currUser.setId(user.getId());
this.setSession(SessionConstants.USER, currUser);
return info;
} else {
return null;
}
}
/**
* 设置session
* @param key key
* @param value value
*/
private void setSession(Object key, Object value) {
Subject currentUser = SecurityUtils.getSubject();
if (null != currentUser) {
Session session = currentUser.getSession();
if (null != session) {
session.setAttribute(key, value);
}
}
}
/**
* 参考文档: http://www.tuicool.com/articles/rEvqym
* 参考文档: http://sishuok.com/forum/blogPost/list/7461.html
* 参考文档: http://m.blog.youkuaiyun.com/blog/LHacker/19340757
*/
public void clearCache() {
Subject subject = SecurityUtils.getSubject();
super.clearCachedAuthorizationInfo(subject.getPrincipals());
}
/**
* 通过身份信息, 清空该用户的权限缓存
* 参考: http://m.blog.youkuaiyun.com/blog/LHacker/19340757
* @param principle 身份信息
*/
public void clearAuthorizationCacheByPrinciple(String principle) {
String cacheName = this.getAuthorizationCacheName();
Cache<Object, Object> cache = this.getCacheManager().getCache(cacheName);
Set<Object> keys = cache.keys();
if (CollectionUtils.isNotEmpty(keys)) {
for (Object key : keys) {
SimplePrincipalCollection spc = (SimplePrincipalCollection) key;
if (principle.equals(spc.toString())) {
cache.remove(key);
break;
}
}
}
}
//自定义认证授权,替代默认的用户名密码验证
@Override
protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)
throws AuthenticationException {
UsernamePasswordCaptchaToken captchaToken = (UsernamePasswordCaptchaToken)token;
if(!captchaToken.getUsername().equals(info.getPrincipals().toString())){
String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";
throw new IncorrectCredentialsException(msg);
}
}
}
UsernamePasswordCaptchaToken类
package com.jusfoun.socialgrid.shiro;
import org.apache.shiro.authc.UsernamePasswordToken;
public class UsernamePasswordCaptchaToken extends UsernamePasswordToken{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* 验证码
*/
private String captcha;
/**
* 用户名
*/
private String username;
/**
* 密码, in char[] format
*/
private char[] password;
/**
* 主机名称或ip
*/
private String host;
/**
* 是否记住我
* 默认值:<code>false</code>
*/
private boolean rememberMe = false;
/**
* 构造方法
* @param captcha验证码
* @param username用户名
*/
public UsernamePasswordCaptchaToken(String username,String captcha) {
super();
this.captcha = captcha;
this.username = username;
}
public String getCaptcha() {
return captcha;
}
public void setCaptcha(String captcha) {
this.captcha = captcha;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public char[] getPassword() {
return password;
}
public void setPassword(char[] password) {
this.password = password;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
public void setHost(String host) {
this.host = host;
}
@Override
public Object getPrincipal() {
return getUsername();
}
@Override
public Object getCredentials() {
return getPassword();
}
@Override
public boolean isRememberMe() {
// TODO Auto-generated method stub
return rememberMe;
}
@Override
public String getHost() {
return host;
}
}