SpringBoot+JWT实现登录状态管理(任意位置获得用户信息)

SpringBoot+JWT实现登录状态管理

介绍

​ 本文实现登录状态管理采用如下技术,全局异常中心、全局获得用户信息、自定义返回类。
项目地址:https://gitee.com/jiang_ming_hong/spring-boot–jwt.git

实现过程

1.需要使用的依赖包

		 <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--JWT的依赖-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>
          <!--lombok-->
		<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

2.编写自定义返回类

public class R { 
    private static HashMap map = new HashMap();

    public static Map succeed(String msg) { 
        map.put("msg", msg);
        map.put("code", 200);
        return map;
    }

    public static Map succeed(String msg, Object data) { 
        map.put("code", 200);
        map.put("msg", msg);
        map.put("data", data);
        return map;
    }

    public static Map succeed(int code, String msg, Object data) { 
        map.put("msg", msg);
        map.put("data", data);
        map.put("code", code);
        return map;
    }

}

3.全局异常类

全局异常中心就是把异常集中在一个类中,方便管理异常。

@Configuration
@ControllerAdvice(annotations = { RestController.class, Controller.class})
@ResponseBody
public class GlobalException { 

    @ExceptionHandler(SignatureVerificationException.class)
    public Map testException(SignatureVerificationException signatureVerificationException) { 
        return R.succeed("签名异常");
    }

    @ExceptionHandler(TokenExpiredException.class)
    public Map testException(TokenExpiredException tokenExpiredException) { 
        return R.succeed("token过期");
    }

    @ExceptionHandler(AlgorithmMismatchException.class)
    public Map testException(AlgorithmMismatchException AlgorithmMismatchException) { 
        return R.succeed("加密算法不匹配");
    }

    @ExceptionHandler(Exception.class)
    public Map testException(Exception exception) { 
        return R.succeed("出错了");
    }

}

4.全局用户信息类

根据token值取出用户的信息,当需要用户这些信息时直接取就行,不用从数据库中取。

public class BaseUserInfo { 

    private static final ThreadLocal<Map<String, String>> THREAD_LOCAL = new ThreadLocal<>();

    //判断线程map是否为空,为空就添加一个map
    public static Map<String, String> getLocalMap() { 
        Map<String, String> map = THREAD_LOCAL.get();
        if (map == null) { 
            map = new HashMap<>(10);
            THREAD_LOCAL.set(map);
        }
        return map;
    }
    //把用户信息添加到线程map中
    public static void set(String key, String name) { 
        Map<String, String> map = getLocalMap();
        map.put(key, name);
    }
    //获得线程map中的数据
    public static String get(String key) { 
        Map<String, String> map = getLocalMap();
        return map.get(key);
    }
}

5.JWT封装类

@Slf4j
public class JWTUtils { 
    /** * 盐值 */
    private static final String SING="123456";


    /** * 生成令牌 * @param map payload载荷声明参数 * @return */
    public  static String getToken(Map<String,String> map){ 
        //获取日历对象
        Calendar calendar=Calendar.getInstance();
        //默认7天过期
        calendar.add(Calendar.DATE, 7);
        //新建一个JWT的Builder对象
        JWTCreator.Builder builder = JWT.create();
        //将map集合中的数据设置进payload
        map.forEach((k,v)->{ 
            builder.withClaim(k, v);
        });
        //设置过期时间和签名
        log.info("时间={}"+calendar.getTime());
        String sign = builder.withExpiresAt(calendar.getTime()).sign(Algorithm.HMAC256(SING));

        return sign;
    }

    /** * 验签并返回DecodedJWT * @param token 令牌 */
    public  static DecodedJWT getTokenInfo(String token){ 
       return JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
    }
}

6.用户枚举

@Getter
public enum UserInfoEnu { 
    user("name"),
    pass("pass");
    private String code;

    UserInfoEnu(String code) { 
        this.code = code;
    }
}

7.配置拦截器

控制那些请求被拦截或者那些请求不被拦截

@Configuration
public class SpringMvcConfig implements WebMvcConfigurer { 

    /** * 自定义拦截器 * @param registry */
    @Override
    public void addInterceptors(InterceptorRegistry registry) { 
        registry.addInterceptor(new MyHandler())
                //拦截全部
                .addPathPatterns("/**")
                //不需拦截的请求
                .excludePathPatterns(this.exclud());
    }
    /** * 不需拦截的请求 */
    public String[] exclud(){ 
        String[] urls= { 
                "/login"
        };
        return urls;
    }
}

8.编写自定义拦截器

验证Token信息是否正确,不正确提示相应的错误

public class MyHandler implements HandlerInterceptor { 

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){ 
        //获得请求头里的TOKEN数据
        String token = request.getHeader("token");
        //根据token解析数据,因为配置了全局异常处理中心,如果有异常会在全局异常中心处理异常
        DecodedJWT tokenInfo = JWTUtils.getTokenInfo(token);
        //获得用户信息
        String name = tokenInfo.getClaim("name").asString();
        String pass = tokenInfo.getClaim("pass").asString();
        //存储用户信息到ThreadLocal中
        BaseUserInfo.set("name",name);
        BaseUserInfo.set("pass",pass);
        return true;
    }
 }
}

9.请求类

getBaseUserInfo()方法中BaseUserInfo.get()可以获得用户信息。

@RestController
public class testController { 


    /** * 获得用户信息 * * @return */
    @PostMapping("test")
    public String getBaseUserInfo() { 
    //获得用户信息
        String name = BaseUserInfo.get(UserInfoEnu.user.getCode());
        String pass = BaseUserInfo.get(UserInfoEnu.pass.getCode());
        return "name:" + name + "-----pass:" + pass;
    }

    /** * 模拟用户登录 * * @param name * @param pass * @return */
    @GetMapping("/login")
    public Map login(String name, String pass) { 
        Map<String, String> map = new HashMap<>();
        map.put("name", name);
        map.put("pass", pass);
        String token = JWTUtils.getToken(map);
        return R.succeed(200, "登录成功", token);
    }

}

测试效果图

模拟登录

《SpringBoot+JWT实现登录状态管理(任意位置获得用户信息)》

登录后获得用户信息

在用户登录成功后,因该把token值存在前端的请求头里。这里只是在Postman中请求。
用户一信息
《SpringBoot+JWT实现登录状态管理(任意位置获得用户信息)》
用户二信息
《SpringBoot+JWT实现登录状态管理(任意位置获得用户信息)》

把token值故意写错

可以看到提示未登录
《SpringBoot+JWT实现登录状态管理(任意位置获得用户信息)》

    原文作者:踏行JAVA
    原文地址: https://blog.csdn.net/qq_41343166/article/details/117880683
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞