SpringBoot 通過token進行身份驗證,存儲redis


代碼:

public interface TokenManager {

    /**
     * 創建token
     * @param userInfo
     * @return
     */
    String getToken(UserInfo userInfo);

    /**
     * 刷新用戶
     * @param token
     */
    void refreshUserToken(String token);

    /**
     * 用戶退出登陸
     * @param token
     */
    void loginOff(String token);

    /**
     * 獲取用戶信息
     * @param token
     * @return
     */
    UserInfo getUserInfoByToken(String token);

}

具體實現:

@Component
public class RedisTokenManager implements TokenManager {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private GlobalConfig globalConfig;

    /**
     * 創建token
     * @param userInfo
     * @return
     */
    public String getToken(UserInfo userInfo){
        //使用uuid作為源token
        String token = UUID.randomUUID().toString().replace("-", "");
        String token_format=String.format(Constants.TOKEN_FORMAT,token);
        redisUtils.set(token_format,userInfo,globalConfig.getTokenExpires());
        return token;
    }

    /**
     * 刷新用戶
     * @param token
     */
    public void refreshUserToken(String token){
        token=String.format(Constants.TOKEN_FORMAT,token);
        if(redisUtils.exists(token)){
            redisUtils.setExpireTime(token, globalConfig.getTokenExpires());
        }
    }

    /**
     * 用戶退出登陸
     * @param token
     */
    public void loginOff(String token){
         token=String.format(Constants.TOKEN_FORMAT,token);
         redisUtils.remove(token);
    }

    /**
     * 獲取用戶信息
     * @param token
     * @return
     */
    public UserInfo getUserInfoByToken(String token){
        token=String.format(Constants.TOKEN_FORMAT,token);
        if(redisUtils.exists(token)){
            return (UserInfo)redisUtils.get(token);
        }
        return null;
    }
}

對TokenManager進行二次封裝,每次操作不需要token參數

@Component
public class AuthManager {

    @Autowired
    private TokenManager tokenManager;

    /**
     * 獲取請求體
     * @return
     */
    public HttpServletRequest getRequest(){
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    /**
     * 登錄
     * @param userInfo
     * @return
     */
    public String signIn(UserInfo userInfo){
        return tokenManager.getToken(userInfo);
    }

    /**
     * 獲取該訪問用戶信息
     * @return
     */
    public UserInfo getUserInfo(){
        HttpServletRequest request=getRequest();
        String token=request.getAttribute(Constants.USER_TOKEN).toString();
        UserInfo userInfo=tokenManager.getUserInfoByToken(token);
        if(userInfo==null){
            throw new AuthException("該用戶已過期", HttpStatus.UNAUTHORIZED.value());
        }
        return userInfo;
    }

    /**
     * 刷新該登錄用戶,延時
     */
    public void refreshUserInfo(){
        HttpServletRequest request=getRequest();
        String token=request.getAttribute(Constants.USER_TOKEN).toString();
         tokenManager.refreshUserToken(token);
    }

    /**
     * 注銷該訪問用戶
     */
    public void loginOff(){
        HttpServletRequest request=getRequest();
        String token=request.getAttribute(Constants.USER_TOKEN).toString();
        tokenManager.loginOff(token);
    }
}

上面是對用戶信息基本操作

對用戶進行控制,部分接口可以不登陸訪問

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthIgnore {

}

攔截器:

@Component
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        AuthIgnore annotation;
        if(handler instanceof HandlerMethod) {
            annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthIgnore.class);
        }else{
            return true;
        }

        //如果有@AuthIgnore注解,則不驗證token
        if(annotation != null){
            return true;
        }

        //獲取用戶憑證
        String token = request.getHeader(Constants.USER_TOKEN);
        if(StringUtils.isBlank(token)){
            token = request.getParameter(Constants.USER_TOKEN);
        }
        if(StringUtils.isBlank(token)){
            Object obj = request.getAttribute(Constants.USER_TOKEN);
            if(null!=obj){
                token=obj.toString();
            }
        }

        //token憑證為空
        if(StringUtils.isBlank(token)){
            throw new AuthException(Constants.USER_TOKEN + "不能為空", HttpStatus.UNAUTHORIZED.value());
        }

        return true;
    }
}

如果token參數必須放在請求體中,直接讀取請求體會報錯,requestbody miss

解決方法:https://www.cnblogs.com/hongdada/p/9171739.html

這里的注解只是標注那些不需要登陸的接口

上面相關redis操作在上面也寫過,請看前面文章。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM