美文网首页
AbstractRememberMeServices细节记录

AbstractRememberMeServices细节记录

作者: Children乏 | 来源:发表于2021-05-19 15:50 被阅读0次

    AbstractRememberMeServices有两个实现类

    实现类 服务端存储token 校验后更新token有效期 cookie内容
    TokenBasedRememberMeServices username, expireTime,token
    PersistentRememberMeToken series,tokenValue

    TokenBasedRememberMeServices

    cookie经Base64解码后,获得字符串数组


    image.png

    内容分别为username, expireTime,token

    这个token是按username:tokenExpiryTime:password:key拼接后进行MD5摘要得到
    其中key是RememberMeConfigurer初始化通过UUID随机生成

        /**
         * Calculates the digital signature to be put in the cookie. Default value is MD5
         * ("username:tokenExpiryTime:password:key")
         */
        protected String makeTokenSignature(long tokenExpiryTime, String username,
                String password) {
            String data = username + ":" + tokenExpiryTime + ":" + password + ":" + getKey();
            MessageDigest digest;
            try {
                digest = MessageDigest.getInstance("MD5");
            }
            catch (NoSuchAlgorithmException e) {
                throw new IllegalStateException("No MD5 algorithm available!");
            }
    
            return new String(Hex.encode(digest.digest(data.getBytes())));
        }
    

    token校验关键点:会再次使用username:tokenExpiryTime:password:key生成token,并与传入的token作比对
    此处的password来自userDetails,确保了cookie内容的安全性,并可知若用户更改了密码,该token亦会失效

            UserDetails userDetails = getUserDetailsService().loadUserByUsername(
                    cookieTokens[0]);
    
            Assert.notNull(userDetails, () -> "UserDetailsService " + getUserDetailsService()
                    + " returned null for username " + cookieTokens[0] + ". "
                    + "This is an interface contract violation");
    
            // Check signature of token matches remaining details.
            // Must do this after user lookup, as we need the DAO-derived password.
            // If efficiency was a major issue, just add in a UserCache implementation,
            // but recall that this method is usually only called once per HttpSession - if
            // the token is valid,
            // it will cause SecurityContextHolder population, whilst if invalid, will cause
            // the cookie to be cancelled.
            String expectedTokenSignature = makeTokenSignature(tokenExpiryTime,
                    userDetails.getUsername(), userDetails.getPassword());
    
            if (!equals(expectedTokenSignature, cookieTokens[2])) {
                throw new InvalidCookieException("Cookie token[2] contained signature '"
                        + cookieTokens[2] + "' but expected '" + expectedTokenSignature + "'");
            }
    

    PersistentTokenBasedRememberMeServices

    cookie经Base64解码后,获得字符串数组


    image.png

    内容分别为series,tokenValue

    series,tokenValue均为随机生成的Base64字符串,相当于随机生成一份账密

        protected String generateSeriesData() {
            byte[] newSeries = new byte[seriesLength];
            random.nextBytes(newSeries);
            return new String(Base64.getEncoder().encode(newSeries));
        }
    
        protected String generateTokenData() {
            byte[] newToken = new byte[tokenLength];
            random.nextBytes(newToken);
            return new String(Base64.getEncoder().encode(newToken));
        }
    

    其中series作为key在首次生成后即稳定不变,tokenValue在每次校验后会更新,并与series一同写回cookie

        PersistentRememberMeToken newToken = new PersistentRememberMeToken(
                    token.getUsername(), token.getSeries(), generateTokenData(), new Date());
    
            try {
                tokenRepository.updateToken(newToken.getSeries(), newToken.getTokenValue(),
                        newToken.getDate());
                addCookie(newToken, request, response);
            }
            catch (Exception e) {
                logger.error("Failed to update token: ", e);
                throw new RememberMeAuthenticationException(
                        "Autologin failed due to data access problem");
            }
    

    series作为key,将整个PersistentRememberMeToken存储在tokenRepository

    PersistentRememberMeToken

    包含username,series,tokenValue,date
    其中date含义为创建时间,用于判断有效期
    自动登录时会刷新tokenValue与date

    相关文章

      网友评论

          本文标题:AbstractRememberMeServices细节记录

          本文链接:https://www.haomeiwen.com/subject/spppjltx.html