shrio验证cookie有效性

来源:互联网 发布:易打单软件 编辑:程序博客网 时间:2024/06/08 00:32

shrio验证cookie有效性

概述

shrio中提供cookie管理的功能,当用户选择了rememberMe,则下次不需要再登录,而是直接通过本地记录的cookie进行验证,然后就可以访问权限为user的页面。

问题

shiro提供清除用户权限的功能,但是那是在代码中动态控制的,你修改了某个用户的权限,可以调用clearCachedAuthorizationInfo(principals)清除权限信息。但是如果是直接改了数据库里的信息(虽然按道理不应该出这种套路),那么它取cookie的时候就不会再验证,不验证用户名密码是否正确,不验证用户里的信息是否有变化。

流程

shiro中解析客户端发来的cookie其实主要就是调用AbstractRememberMeManager中的getRememberedPrincipals():

public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext) {        PrincipalCollection principals = null;        try {            byte[] re = this.getRememberedSerializedIdentity(subjectContext);            if(re != null && re.length > 0) {                principals = this.convertBytesToPrincipals(re, subjectContext);            }        } catch (RuntimeException var4) {            principals = this.onRememberedPrincipalFailure(var4, subjectContext);        }        return principals;    }

CookieRememberMeManager中实现了抽象方法getRememberedSerializedIdentity():

protected byte[] getRememberedSerializedIdentity(SubjectContext subjectContext) {        if(!WebUtils.isHttp(subjectContext)) {            if(log.isDebugEnabled()) {                String wsc1 = "SubjectContext argument is not an HTTP-aware instance.  This is required to obtain a servlet request and response in order to retrieve the rememberMe cookie. Returning immediately and ignoring rememberMe operation.";                log.debug(wsc1);            }            return null;        } else {            WebSubjectContext wsc = (WebSubjectContext)subjectContext;            if(this.isIdentityRemoved(wsc)) {                return null;            } else {                HttpServletRequest request = WebUtils.getHttpRequest(wsc);                HttpServletResponse response = WebUtils.getHttpResponse(wsc);                String base64 = this.getCookie().readValue(request, response);                if("deleteMe".equals(base64)) {                    return null;                } else if(base64 != null) {                    base64 = this.ensurePadding(base64);                    if(log.isTraceEnabled()) {                        log.trace("Acquired Base64 encoded identity [" + base64 + "]");                    }                    byte[] decoded = Base64.decode(base64);                    if(log.isTraceEnabled()) {                        log.trace("Base64 decoded byte array length: " + (decoded != null?decoded.length:0) + " bytes.");                    }                    return decoded;                } else {                    return null;                }            }        }    }

主要就是进行解密,然后再返回去convertBytesToPrincipals()

解决方案

熟悉了大致的流程,应该可以想到一个解决方案。就是继承CookirRememberMeManager,重写getRememberedPrincipals()

public class MyRememberMeManager extends CookieRememberMeManager {    @Autowired    LoginService loginService;    @Override    public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext) {        PrincipalCollection principals =  super.getRememberedPrincipals(subjectContext);        if(null == principals)            return null;        User loginUser = (User) principals.getPrimaryPrincipal();        User checkUser = loginService.check(loginUser.getUsername(), loginUser.getPassword());        if(null == checkUser)            return null;        loginUser.setLevel(checkUser.getLevel());        loginUser.setCounty(checkUser.getCounty());        loginUser.setCity(checkUser.getCity());        loginUser.setTown(checkUser.getTown());        loginUser.setVillage(checkUser.getVillage());        loginUser.setDescription(checkUser.getDescription());        return principals;    }}
原创粉丝点击