zoukankan      html  css  js  c++  java
  • 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操作在上面也写过,请看前面文章。

  • 相关阅读:
    解决mongod端口占用问题
    MongoDB操作
    ssh 带密码私钥 输入密码
    sequence
    使用plsql导入dmp文件缺少imp*.exe
    oracle查看锁表进程,杀掉锁表进程
    oracle
    常用shell命令
    ORA-03113: end-of-file on & ORA-07445
    ORA-39126: Worker unexpected fatal error in KUPW$WORKER.PUT_DDLS
  • 原文地址:https://www.cnblogs.com/hongdada/p/9187981.html
Copyright © 2011-2022 走看看