package com.gxx.manage.shiro;
import java.util.List;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.log4j.Logger;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import com.gxx.manage.base.vo.Permission;
import com.gxx.manage.base.vo.Role;
import com.gxx.manage.base.vo.User;
import com.gxx.manage.service.UserService;
/**
*
* - Title:
* -
* 自定义授权领域类
*
* - Description:
* -
*
none
*
*
*
* @author Administrator
* @version 1.0, 2015年9月19日
* @since manage
*
*/
public class ManageAuthorizingRealm extends AuthorizingRealm {
/**
* 日志处理器
*/
Logger logger = Logger.getLogger(ManageAuthorizingRealm.class);
@Autowired
UserService userService;
/**
* 为当前登录的Subject授予角色和权限
* @see 经测试:本例中该方法的调用时机为需授权资源被访问时
* @see 经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache
* @see 个人感觉若使用了Spring3.1开始提供的ConcurrentMapCache支持,则可灵活决定是否启用AuthorizationCache
* @see 比如说这里从数据库获取权限信息时,先去访问Spring3.1提供的缓存,而不使用Shior提供的AuthorizationCache
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
/**
* 获取当前登录的用户名,等价于(String)principals.fromRealm(this.getName()).iterator().next()
*/
String currentUsername = (String)super.getAvailablePrincipal(principals);
logger.info("为当前登录的Subject授予角色和权限,用户名:" + currentUsername);
User user = userService.getUserByName(currentUsername);
if(null == user){
/**
* 不存在用户则返回null
*/
logger.error("不存在用户");
return null;
}
/**
* 为当前用户查询角色和权限
*/
SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
List roles = userService.queryRolesByUserId(user.getId());
for(Role role : roles){
logger.info("拥有角色:" + role.getRole());
simpleAuthorInfo.addRole(role.getRole());
List permissions = userService.queryPermissionsByRoleId(role.getId());
for(Permission permission : permissions){
logger.info("拥有权限:" + permission.getPermission());
simpleAuthorInfo.addStringPermission(permission.getPermission());
}
}
return simpleAuthorInfo;
}
/**
* 验证当前登录的Subject
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
/**
* 获取基于用户名和密码的令牌
* 实际上这个token是从LoginController里面currentUser.login(token)传过来的
* 两个token的引用都是一样的
*/
logger.info("验证当前Subject时获取到token为" + ReflectionToStringBuilder.
toString(((UsernamePasswordToken)token), ToStringStyle.MULTI_LINE_STYLE));
User user = userService.getUserByName(((UsernamePasswordToken)token).getUsername());
if(null == user){
/**
* 不存在用户则返回null
*/
return null;
}
/**
* 这里不用比较,直接返回就好,shiro会自动比较
*/
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo
(user.getName(), user.getPassword(), this.getName());
return authenticationInfo;
}
}