前后端分离基于jwt的用户认证实现

本文介绍了在前后端分离的项目中,如何使用JWT(JSON Web Token)进行用户认证。首先,展示了在登录接口后端生成JWT token的步骤,包括设置有效期、存储用户信息等。接着,说明了前端如何将token存储在cookie中,并在访问受限资源时在请求头中携带token。最后,讲解了后端如何通过拦截器验证请求头中的token,处理预检请求并进行token的有效性和合法性检查。
摘要由CSDN通过智能技术生成
  • 所需依赖java-jwt与jjwt
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.15.0</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
  • 在登录接口的业务层生成token
 JwtBuilder builder = Jwts.builder();
 HashMap<String, Object> map = new HashMap<>();
 map.put("key1","value1");//可以使用map存储用户角色权限信息
 String token = builder.setSubject(username)
        .setIssuedAt(new Date())//设置token的生成时间
        .setId(users.getUserId() + "")//设置用户id为token的id
        .setClaims(map)//map中可以存放用户的角色权限信息
        .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000))//设置token的过期使时间
        .signWith(SignatureAlgorithm.HS256, "yongxin")//设置加密方式和加密密码
        .compact();
  • 前端登录页面拿到token并将其存储在cookie中
	//如果登录成功,把token存储到cookie中
	setCookieValue("token",res.data.msg);
	//这里把cookie的操作封装在一个js文件中
  • 前端访问受限页面时间向后端请求在headers中携带token

前端但凡访问受限资源,都必须携带token发送请求,token可以通过请求行(params),请求头(header)以及请求体(data)传递,但是习惯性使用请求头(header)传递

				created:function(){
					this.token = getCookieValue("token");
					axios({
						method:"get",
						url:baseUrl+"/shoppingCart/list",
						headers:{
							token:this.token
						}
					}).then(function(res){
						//判断是否合法,合法则渲染页面
					})
				}
  • 后端在拦截器中验证前端请求携带的token

注意:当前端发送的请求携带自定义请求头时,浏览器的预检机制会发送一次预检请求(mehtod=“options”),后端响应预检请求,之后前端才会发送真正携带数据的请求。因此我们要在拦截器中加以判断。

@Component
public class CheckTokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //放行预检请求
        String method = request.getMethod();
        if ("OPTIONS".equalsIgnoreCase(method)){
            return true;
        }
        String token = request.getHeader("token");
        if (token ==null){
            ResultVO resultVO = new ResultVO(1001, "请先登录", null);
            doResponse(response,resultVO);
        }else {
            //验证token
            JwtParser parser = Jwts.parser();
            parser.setSigningKey("yongxin");//解析token的SigningKey必须与生成token的密码一致
            try {
                Jws<Claims> claimsJws = parser.parseClaimsJws(token);
                Claims body = claimsJws.getBody();//获取token中的用户数据
                String subject = body.getSubject();
                String v1 = body.get("key1", String.class);
                ResultVO resultVO = new ResultVO(1000, "success", null);
                doResponse(response,resultVO);
            } catch (UnsupportedJwtException e){
                ResultVO resultVO = new ResultVO(1001, "登录过期,请重新登录!", null);
                doResponse(response,resultVO);
            } catch (ExpiredJwtException e){
                ResultVO resultVO = new ResultVO(1001, "token不合法,请自重!", null);
                doResponse(response,resultVO);
            } catch (Exception e){
                ResultVO resultVO = new ResultVO(1001, "请重新登录!", null);
                doResponse(response,resultVO);
            }
        }
        return false;
    }
    private void doResponse(HttpServletResponse response, ResultVO resultVO) throws IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        PrintWriter writer = response.getWriter();
        String s = new ObjectMapper().writeValueAsString(resultVO);
        writer.println(s);
        writer.flush();
        writer.close();

    }
}

注册拦截器

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Autowired
    private CheckTokenInterceptor checkTokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(checkTokenInterceptor)
                .addPathPatterns("/shoppingCart/**");//需要拦截的受限资源请求
                /*.excludePathPatterns("/users/**");*/
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LeBron永鑫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值