shrio验证cookie有效性

本文探讨了Shiro框架中cookie验证的有效性问题及其解决方案。当用户选择记住我功能时,Shiro会保存cookie用于后续访问。然而,直接更改数据库中的用户信息可能导致cookie验证失效。文章提出了一种自定义RememberMeManager的方法来解决这一问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值