shiro的登陸與授權都是通過realm來的,這是一個自定義的realm。
public class RealmManager extends AuthorizingRealm {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private SysUserManager userManager;
@Autowired
private SysMenuResourceViewManager menuResourceViewManager;
@Autowired
private SessionDAO sessionDAO;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //授權
if (!SecurityUtils.getSubject().isAuthenticated()) {
doClearCache(principals);
SecurityUtils.getSubject().logout();
return null;
}
String username = (String) principals.getPrimaryPrincipal();
SysUser user = userManager.selectByUsername(username);
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
List<SysMenuResourceView> menuResourceViewList = menuResourceViewManager.loadUserResource(user.getId());
Set<String> perms = new HashSet<String>();
for(SysMenuResourceView view : menuResourceViewList){
perms.add(view.getMenuEname());
}
authorizationInfo.setStringPermissions(perms);
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { //登陸
UsernamePasswordToken token = (UsernamePasswordToken)authcToken;
String username = token.getUsername();
SysUser user = userManager.selectByUsername(username);
if (StrUtils.isEmpty(user.getId())) {
throw new UnknownAccountException();// 沒找到帳號
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(), // 用戶名
user.getPassword(), // 密碼
getName() // realm name
);
return authenticationInfo;
}
/**
* 清除權限緩存
* @param username
*/
public void clearUserChache(String username){
logger.info("************開始清除用戶權限緩存**************");
Subject sub = SecurityUtils.getSubject();
PrincipalCollection pri = sub.getPrincipals();
PrincipalCollection principals = new SimplePrincipalCollection(
username, getName());
System.out.println(pri.hashCode());
System.out.println(principals.hashCode());
this.clearCachedAuthorizationInfo(principals);
logger.info("********用戶:"+username+"的權限緩存已經清除***********");
}
/**
* 清除所有用戶權限
*/
public void clearAllUserCache(){
Collection<Session> sessions = sessionDAO.getActiveSessions();
Iterator it = sessions.iterator();
while(it.hasNext()) {
Session session = (Session) it.next();
String username = session.getAttribute("org.apache.shiro.subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY").toString();
this.clearUserChache(username);
}
}
最後面兩個是原本沒有的方法,加這兩個方法是因爲shiro爲了提高效率採用了cache的形式來存儲用戶的登陸信息和權限信息,如果此時用戶的密碼改變了或者是權限改變了正常情況下是需要重新登陸纔可以看見效果,這樣在體驗上很不好而且用戶是無法控制的你不能決定他的行爲,所以我們要在改變權限的時候將cache裏面的用戶信息清除掉。
public void clearUserAuthByUsername(String username){
RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
RealmManager realm = (RealmManager) rsm.getRealms().iterator().next();
realm.clearUserChache(username);
}
這是調用的方法,由於我這裏只一個realm所以就直接進行了強轉,如果realm很多就要寫一個接口讓realm去實現了。