spring mvc+Mybatis整合shiro 第二章Realm

时间:2022-01-17 23:17:07

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去实现了。