SpringBoot实现基于token的登录验证

  1. 基于token的登录验证实现原理:客户端通过用户名和密码调用登录接口,当验证数据库中存在该用户后,将用户的信息按照token的生成规则,生成一个字符串token,返回给客户端,客户端在调用其他接口的时候,需要在请求头上带上token,来验证登录信息<br /> Demo实现代码如下:<br />(因为除登录接口外,其他接口每次都需要验证token信息,所以将验证token信息的部分放在了过滤器里面)<br />————————————————<br />版权声明:本文为CSDN博主「qq_36816062」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

1.导入JWT(JSON WEB TOKEN)依赖

  1. <dependency>
  2. <groupId>io.jsonwebtoken</groupId>
  3. <artifactId>jjwt</artifactId>
  4. <version>0.6.0</version>
  5. </dependency>

2.Jwt工具类,包括token的生成和验证

(加密秘钥先自己随便写了一个)

  1. package com.lzs.haiyan.utils;
  2. import io.jsonwebtoken.*;
  3. import org.springframework.stereotype.Component;
  4. import java.util.Date;
  5. import java.util.HashMap;
  6. import java.util.Map;
  7. /**
  8. * @author : liangzesheng
  9. * @Date : 2022-02-17
  10. * @Description : jwt工具类
  11. */
  12. @Component
  13. public class JwtUtils {
  14. /**
  15. * 过期时间7200s
  16. */
  17. private static final long EXPIRE_TIME=7200*1000;
  18. /**
  19. * 加密密钥
  20. */
  21. private static final String KEY = "haiyan";
  22. /**
  23. * 生成token
  24. * @param uuid 用户uuid
  25. * @param loginnum 用户账号
  26. * @return
  27. */
  28. public static String createToken(String uuid,String loginnum){
  29. Map<String,Object> header = new HashMap();
  30. header.put("typ","JWT");
  31. header.put("alg","HS256");
  32. //setID:用户ID
  33. //setExpiration:token过期时间 当前时间+有效时间
  34. //setSubject:用户名
  35. //setIssuedAt:token创建时间
  36. //signWith:加密方式
  37. JwtBuilder builder = Jwts.builder().setHeader(header)
  38. .setId(uuid)
  39. .setExpiration(new Date(System.currentTimeMillis()+EXPIRE_TIME))
  40. .setSubject(loginnum)
  41. .setIssuedAt(new Date())
  42. .signWith(SignatureAlgorithm.HS256,KEY);
  43. return builder.compact();
  44. }
  45. /**
  46. * 验证token是否有效
  47. * @param token 请求头中携带的token
  48. * @return token验证结果 2-token过期;1-token认证通过;0-token认证失败
  49. */
  50. public static int verify(String token){
  51. Claims claims = null;
  52. try {
  53. //token过期后,会抛出ExpiredJwtException 异常,通过这个来判定token过期,
  54. claims = Jwts.parser().setSigningKey(KEY).parseClaimsJws(token).getBody();
  55. }catch (ExpiredJwtException e){
  56. return 2;
  57. }
  58. //从token中获取用户id,查询该Id的用户是否存在,存在则token验证通过
  59. String uuid = claims.getId();
  60. User user = haiyanFilter.selectUserByUuId(uuid);
  61. if(user != null){
  62. return 1;
  63. }else{
  64. return 0;
  65. }
  66. return 1;
  67. }
  68. }

3.过滤器,实现filter接口

每有请求都要先经过过滤器再传入到接口方法

  1. package com.lzs.haiyan.filter;
  2. import cn.hutool.json.JSONObject;
  3. import com.lzs.haiyan.utils.JwtUtils;
  4. import org.springframework.stereotype.Component;
  5. import javax.servlet.*;
  6. import javax.servlet.http.HttpServletRequest;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. import java.util.HashMap;
  10. import java.util.Map;
  11. /**
  12. * token鉴权 过滤器
  13. * @author : lzs
  14. * @Date : 2022-02-17
  15. * @Description :
  16. */
  17. @Component
  18. public class HaiyanFilter implements Filter {
  19. @Override
  20. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  21. Map<String, String> map = new HashMap<>();
  22. String url = ((HttpServletRequest) servletRequest).getRequestURI();
  23. if (url != null) {
  24. //注册与登录请求直接放行
  25. if ("/user/login".equals(url)||"/user/regist".equals(url)) {
  26. filterChain.doFilter(servletRequest, servletResponse);
  27. return;
  28. } else {
  29. //其他请求验证token
  30. String token = ((HttpServletRequest) servletRequest).getHeader("token");
  31. if (token != null && token.length() > 0 && token.trim().length() > 0) {
  32. //token验证结果
  33. int verify = JwtUtils.verify(token);
  34. if (verify != 1) {
  35. //验证失败
  36. if (verify == 2) {
  37. map.put("errorMsg", "token已过期");
  38. } else if (verify == 0) {
  39. map.put("errorMsg", "用户信息验证失败");
  40. }
  41. } else if (verify == 1) {
  42. //验证成功,放行
  43. filterChain.doFilter(servletRequest, servletResponse);
  44. return;
  45. }
  46. } else {
  47. //token为空的返回
  48. map.put("errorMsg", "未携带token信息");
  49. }
  50. }
  51. JSONObject jsonObject = new JSONObject(map);
  52. servletResponse.setContentType("application/json");
  53. //设置响应的编码
  54. servletResponse.setCharacterEncoding("utf-8");
  55. //响应
  56. PrintWriter pw = servletResponse.getWriter();
  57. pw.write(jsonObject.toString());
  58. pw.flush();
  59. pw.close();
  60. }
  61. }
  62. }