/**
* @author xichao.dong
* @email 406592176@qq.com
* @date 2014-8-15 上午8:50:38
* @company (开发公司) 珠海市冰川软件有限公司
* @copyright (版权) 本文件归属珠海市冰川软件有限公司所有
* @version V1.0
* @modify (修改) : 2014-8-15 上午8:50:38 xichao.dong
* @Review (审核人) :xichao.dong
*/
package com.glacier.frame.compent.realm;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.StringUtils;
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.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import com.glacier.basic.util.RandomGUID;
import com.glacier.frame.dao.system.AuthorityMapper;
import com.glacier.frame.dao.system.LoginLogMapper;
import com.glacier.frame.dao.system.RoleMapper;
import com.glacier.frame.dao.system.UserMapper;
import com.glacier.frame.entity.system.Authority;
import com.glacier.frame.entity.system.LoginLog;
import com.glacier.frame.entity.system.User;
import com.glacier.frame.entity.system.UserExample;
import com.glacier.frame.service.system.UserService;
import com.glacier.security.util.Encodes;
/**
*
* @ClassName: CustomPermissionsRealm
* @Description: TODO(管理员进行自定义执行认证和授权的类)
* @author xichao.dong
* @email 406592176@qq.com
* @date 2014-8-15 上午11:19:33
*/
public class CustomPermissionsRealm extends AuthorizingRealm {
@Autowired
private UserMapper userMapper;
@Autowired
private RoleMapper roleMapper;
@Autowired
private AuthorityMapper authorityMapper;
@Autowired
private LoginLogMapper loginLogMapper;
public CustomPermissionsRealm() {
setName("CustomPermissionsRealm");
}
/*
* (non-Javadoc) <p>Title: doGetAuthorizationInfo</p> <p>Description: 授权</p>
* <p>当缓存中没有用户的授权信息的时候会从该方法中加载,缓存到文件中</p>
*
* @param principals
*
* @return
*
* @see
* org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache
* .shiro.subject.PrincipalCollection)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Subject pricipalSubject = SecurityUtils.getSubject();
User principalUser = (User) pricipalSubject.getPrincipal();// 获取通过认证用户
List<Authority> authorityList = authorityMapper.selectByUserId(principalUser.getUserId());// 获取用户的权限集合(用户和用户组的角色权限)
if (null != authorityList && authorityList.size() > 0) {
SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo();// 创建返回权限对象
for (Authority authority : authorityList) {
if (null != authority && StringUtils.isNotBlank(authority.getActions())) {
String[] actionString = authority.getActions().split(",");
for (String action : actionString) {
// shiro权限字符串为:“当前资源英文名称:操作名英文名称”
// 对action进行分割,避免权限范围对其造成的影响
String[] authStr = action.split(":");
authInfo.addStringPermission(authority.getMenuEnName() + ":" + authStr[0]);// 设置权限操作(设置Permission)
}
}
}
return authInfo;
}
return null;
}
/*
* (non-Javadoc) <p>Title: doGetAuthenticationInfo</p> <p>Description:
* 认证回调函数,登录时调用.</p>
*
* @param authtoken
*
* @return
*
* @throws AuthenticationException
*
* @see
* org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org
* .apache.shiro.authc.AuthenticationToken)
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
CaptchaUsernamePasswordToken token = (CaptchaUsernamePasswordToken) authcToken;
String username = token.getUsername();
if (null != username && !"".equals(username)) {
UserExample userExample = new UserExample();
userExample.createCriteria().andUsernameEqualTo(username);
User principalUser = userMapper.selectByExample(userExample).get(0);
if (null != principalUser) {
// 用户状态为启用或隐藏让其通过认证
byte[] salt = Encodes.decodeHex(principalUser.getSalt());
AuthenticationInfo info = new SimpleAuthenticationInfo(principalUser, principalUser.getPassword(), ByteSource.Util.bytes(salt), getName());// 将用户的所有信息作为认证对象返回
clearCache(info.getPrincipals());// 认证成功后清除之前的缓存
updatePrincipalUserInfo(token, principalUser);// 更新用户登录信息
return info;
} else {
throw new DisabledAccountException();
}
}
return null;
}
/**
* @param token
* @param principalUser
* @Title: updatePrincipalUserInfo
* @Description: TODO(更新用户登录信息)
* @param
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws 备注
* <p>
* 已检查测试:Green
* <p>
*/
private void updatePrincipalUserInfo(CaptchaUsernamePasswordToken token, User principalUser) {
User lastPrincipalUser = new User();
lastPrincipalUser.setUserId(principalUser.getUserId());
lastPrincipalUser.setLastLoginIpAddress(token.getHost());// 设定最后登录时间
lastPrincipalUser.setLastLoginTime(new Date());
lastPrincipalUser.setLoginCount(principalUser.getLoginCount() + 1);
userMapper.updateByPrimaryKeySelective(lastPrincipalUser);//更新用户信息
LoginLog loginLog = new LoginLog();
loginLog.setLoginlogId(RandomGUID.getRandomGUID());
loginLog.setLoginIp(token.getHost());
loginLog.setLoginTime(new Date());
loginLog.setLoginUser(principalUser.getUserCnName());
loginLog.setUserId(principalUser.getUserId());
loginLogMapper.insert(loginLog);//插入登录日志
}
/**
* 更新用户授权信息缓存.
*/
public void clearCachedAuthorizationInfo(String principal) {
SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
clearCachedAuthorizationInfo(principals);
}
/**
* 清除所有用户授权信息缓存.
*/
public void clearAllCachedAuthorizationInfo() {
Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
if (cache != null) {
for (Object key : cache.keys()) {
cache.remove(key);
}
}
}
/**
* 设定Password校验的Hash算法与迭代次数.
*/
@PostConstruct
public void initCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(UserService.HASH_ALGORITHM);
matcher.setHashIterations(UserService.HASH_INTERATIONS);
setCredentialsMatcher(matcher);
}
}