1. 程式人生 > >shiro 之許可權驗證問題

shiro 之許可權驗證問題

/**
 * Copyright &copy; 2012-2014 <a href="https://www.mycomm.com/mycommcrm">MyComm CRM</a> All rights reserved.
 */
package com.thinkgem.jeesite.modules.sys.security;


import java.io.Serializable;
import java.util.Collection;
import java.util.List;


import javax.annotation.PostConstruct;



import org.apache.commons.lang3.StringUtils;
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.credential.HashedCredentialsMatcher;

import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;

import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;


import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.servlet.ValidateCodeServlet;
import com.thinkgem.jeesite.common.utils.Encodes;
import com.thinkgem.jeesite.common.utils.SpringContextHolder;
import com.thinkgem.jeesite.common.web.Servlets;
import com.thinkgem.jeesite.modules.sys.entity.Menu;
import com.thinkgem.jeesite.modules.sys.entity.Role;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.service.SystemService;
import com.thinkgem.jeesite.modules.sys.utils.LogUtils;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
import com.thinkgem.jeesite.modules.sys.web.LoginController;


/**
 * 系統安全認證實現類
 * @author MyComm
 * @version 2014-7-5
 */
@Service
//@DependsOn({"userDao","roleDao","menuDao"})
public class SystemAuthorizingRealm extends AuthorizingRealm {


private Logger logger = LoggerFactory.getLogger(getClass());

private SystemService systemService;


/**
* 認證回撥函式, 登入時呼叫
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

int activeSessionSize = getSystemService().getSessionDao().getActiveSessions(false).size();
if (logger.isDebugEnabled()){
logger.debug("login submit, active session size: {}, username: {}, password: {}", activeSessionSize, token.getUsername(), token.getPassword());
}

// 校驗登入驗證碼
if (LoginController.isValidateCodeLogin(token.getUsername(), false, false)){
Session session = UserUtils.getSession();
String code = (String)session.getAttribute(ValidateCodeServlet.VALIDATE_CODE);
if (token.getCaptcha() == null || !token.getCaptcha().toUpperCase().equals(code)){
throw new AuthenticationException("msg:驗證碼錯誤, 請重試.");
}
}

// 校驗使用者名稱密碼
User user = getSystemService().getUserByLoginName(token.getUsername());
if (user != null) {
if (Global.NO.equals(user.getLoginFlag())){
throw new AuthenticationException("msg:該已帳號禁止登入.");
}
byte[] salt = Encodes.decodeHex(user.getPassword().substring(0,16));
SimpleAuthenticationInfo authenticationInfo =  new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin(), token.getExtNum(),token.getIsReady(),token.getIsCheckin(),token.getSeatTel()), 
user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());
return authenticationInfo;
} else {
return null;
}
}


/**
* 授權查詢回撥函式, 進行鑑權但快取中無使用者的授權資訊時呼叫
*/

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Principal principal = (Principal) getAvailablePrincipal(principals);
// 獲取當前已登入的使用者
if (!Global.TRUE.equals(Global.getConfig("user.multiAccountLogin"))){
Collection<Session> sessions = getSystemService().getSessionDao().getActiveSessions(true, principal, UserUtils.getSession());
if (sessions.size() > 0){
// 如果是登入進來的,則踢出已線上使用者
if (UserUtils.getSubject().isAuthenticated()){
User user = new User();
for (Session session : sessions){
if(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)!=null){
user= UserUtils.get(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY).toString());
}
if(null!=user && null!=principal && (principal.getId()).equals(user.getId())){
getSystemService().getSessionDao().delete(session);
}
}
}
// 記住我進來的,並且當前使用者已登入,則退出當前使用者提示資訊。
else{
UserUtils.getSubject().logout();
throw new AuthenticationException("msg:賬號已在其它地方登入,請重新登入。");
}
}
}
User user = getSystemService().getUserByLoginName(principal.getLoginName());
if (user != null) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
List<Menu> list = UserUtils.getMenuList();
for (Menu menu : list){
if (StringUtils.isNotBlank(menu.getPermission())){
// 新增基於Permission的許可權資訊
for (String permission : StringUtils.split(menu.getPermission(),",")){
info.addStringPermission(permission);
}
}
}
// 新增使用者許可權
info.addStringPermission("user");
// 新增使用者角色資訊
for (Role role : user.getRoleList()){
info.addRole(role.getEnname());
}
// 更新登入IP和時間
getSystemService().updateUserLoginInfo(user);
// 記錄登入日誌
LogUtils.saveLog(Servlets.getRequest(), "系統登入");
return info;
} else {
return null;
}
}

@Override
protected void checkPermission(Permission permission, AuthorizationInfo info) {
authorizationValidate(permission);
super.checkPermission(permission, info);
}

@Override
protected boolean[] isPermitted(List<Permission> permissions, AuthorizationInfo info) {
if (permissions != null && !permissions.isEmpty()) {
            for (Permission permission : permissions) {
authorizationValidate(permission);
            }
        }
return super.isPermitted(permissions, info);
}

@Override
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
authorizationValidate(permission);
return super.isPermitted(principals, permission);
}

@Override
protected boolean isPermittedAll(Collection<Permission> permissions, AuthorizationInfo info) {
if (permissions != null && !permissions.isEmpty()) {
            for (Permission permission : permissions) {
authorizationValidate(permission);
            }
        }
return super.isPermittedAll(permissions, info);
}

/**
* 授權驗證方法
* @param permission
*/
private void authorizationValidate(Permission permission){
// 模組授權預留介面
}

/**
* 設定密碼校驗的Hash演算法與迭代次數
*/
@PostConstruct
public void initCredentialsMatcher() {
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(SystemService.HASH_ALGORITHM);
matcher.setHashIterations(SystemService.HASH_INTERATIONS);
setCredentialsMatcher(matcher);
}

///**
//* 清空使用者關聯許可權認證,待下次使用時重新載入
//*/
//public void clearCachedAuthorizationInfo(Principal principal) {
//SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
//clearCachedAuthorizationInfo(principals);
//}


/**
* 清空所有關聯認證
* @Deprecated 不需要清空,授權快取儲存到session中
*/
@Deprecated
public void clearAllCachedAuthorizationInfo() {
//Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
//if (cache != null) {
//for (Object key : cache.keys()) {
//cache.remove(key);
//}
//}
}


/**
* 獲取系統業務物件
*/
public SystemService getSystemService() {
if (systemService == null){
systemService = SpringContextHolder.getBean(SystemService.class);
}
return systemService;
}

/**
* 授權使用者資訊
*/
public static class Principal implements Serializable {


private static final long serialVersionUID = 1L;

private String id; // 編號
private String loginName; // 登入名
private String name; // 姓名
private String extNum; //分機
private String isReady; //自動就緒
private String isCheckin; //自動簽入
private String seatTel; //座席電話
private boolean mobileLogin; // 是否手機登入

//private Map<String, Object> cacheMap;


public Principal(User user, boolean mobileLogin, String extNum, String isReady, String isCheckin,String seatTel) {
this.id = user.getId();
this.loginName = user.getLoginName();
this.name = user.getName();
this.mobileLogin = mobileLogin;
this.extNum = extNum;
this.isReady = isReady;
this.isCheckin = isCheckin;
this.seatTel = seatTel;
}


public String getId() {
return id;
}


public String getLoginName() {
return loginName;
}


public String getName() {
return name;
}

public String getExtNum() {
return extNum;
}



public String getIsReady() {
return isReady;
}


public String getIsCheckin() {
return isCheckin;
}


public String getSeatTel() {
return seatTel;
}


public void setSeatTel(String seatTel) {
this.seatTel = seatTel;
}


public boolean isMobileLogin() {
return mobileLogin;
}


//@JsonIgnore
//public Map<String, Object> getCacheMap() {
//if (cacheMap==null){
//cacheMap = new HashMap<String, Object>();
//}
//return cacheMap;
//}


/**
* 獲取SESSIONID
*/
public String getSessionid() {
try{
return (String) UserUtils.getSession().getId();
}catch (Exception e) {
return "";
}
}

@Override
public String toString() {
return id;
}


}
}
  1. }