美文网首页
前后端分离JWT Token登录,后端Springboot代码

前后端分离JWT Token登录,后端Springboot代码

作者: 橙子只过今天 | 来源:发表于2021-02-07 10:25 被阅读0次

    参考自文章

    springboot+vue实现token验证

    Springboot+Vue前后端分离实现token登录验证和状态保存

    阮一峰——JSON Web Token 入门教程


    1. 后端Springboot

    目录结构

    image

    1.1 拦截器LoginInteceptor类 (com.chinasoft.config)包

    package com.chinasoft.config;
    
    import java.lang.reflect.Method;
    
    import javax.servlet.http.HttpServletRequest;
    
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.beans.factory.annotation.Autowired;
    
    import org.springframework.stereotype.Component;
    
    import org.springframework.web.method.HandlerMethod;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import org.springframework.web.servlet.ModelAndView;
    
    import com.alibaba.fastjson.JSONObject;
    
    import com.auth0.jwt.JWT;
    
    import com.auth0.jwt.JWTVerifier;
    
    import com.auth0.jwt.algorithms.Algorithm;
    
    import com.auth0.jwt.exceptions.JWTDecodeException;
    
    import com.auth0.jwt.exceptions.JWTVerificationException;
    
    import com.auth0.jwt.interfaces.DecodedJWT;
    
    import com.chinasoft.annotation.PassToken;
    
    import com.chinasoft.annotation.UserLoginToken;
    
    import com.chinasoft.pojo.User;
    
    import com.chinasoft.service.UserService;
    
    /**
    
    * 未登录拦截器
    
    */
    
    @Component
    
    public class LoginInterceptor implements HandlerInterceptor {
    
        @Autowired
    
        private UserService userService;
    
        @Override
    
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
    
        String token = httpServletRequest.getHeader("Authorization");// 从 http 请求头中取出 token
    
            // 如果不是映射到方法直接通过
    
            if (!(object instanceof HandlerMethod)) {
    
                return true;
    
            }
    
            HandlerMethod handlerMethod = (HandlerMethod) object;
    
            Method method = handlerMethod.getMethod();
    
            //检查是否有passtoken注释,有则跳过认证
    
            if (method.isAnnotationPresent(PassToken.class)) {
    
                PassToken passToken = method.getAnnotation(PassToken.class);
    
                if (passToken.required()) {
    
                    return true;
    
                }
    
            }
    
            //检查有没有需要用户权限的注解
    
            if (method.isAnnotationPresent(UserLoginToken.class)) {
    
                UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
    
                if (userLoginToken.required()) {
    
                    // 执行认证,无token
    
                    if (token == null) {
    
                    httpServletResponse.setCharacterEncoding("UTF-8");
    
                    httpServletResponse.setContentType("application/json; charset=utf-8");
    
                try{
    
                      JSONObject json = new JSONObject();
    
                      json.put("msg","token verify fail");
    
                      json.put("code","50000");
    
                      httpServletResponse.getWriter().append(json.toJSONString());
    
                    }catch (Exception e){
    
                      e.printStackTrace();
    
                      httpServletResponse.sendError(500);
    
                      return false;
    
                    }
    
                return false;
    
                    }
    
                    // 获取 token 中的 user id
    
                    String userId = null;
    
                    try {
    
                        userId = JWT.decode(token).getAudience().get(0);
    
                    } catch (JWTDecodeException j) {
    
                    try{
    
                        JSONObject json = new JSONObject();
    
                        json.put("msg","usertoken verify fail");
    
                        json.put("code","401");
    
                        httpServletResponse.getWriter().append(json.toJSONString());
    
                        System.out.println("身份验证错误");
    
                      }catch (Exception e){
    
                        e.printStackTrace();
    
                        httpServletResponse.sendError(401);
    
                        return false;
    
                      }
    
                    return false;
    
                    }
    
                    // 获取用户
    
                    int id = Integer.parseInt(userId);
    
                    User user = userService.findOneUserById(id);
    
                    if (user == null) {
    
                    // 返回错误信息
    
                    try{
    
                        JSONObject json = new JSONObject();
    
                        json.put("msg","no user");
    
                        json.put("code","50000");
    
                        httpServletResponse.getWriter().append(json.toJSONString());
    
                        System.out.println("不存在该用户");
    
                      }catch (Exception e){
    
                        e.printStackTrace();
    
                        httpServletResponse.sendError(500);
    
                        return false;
    
                      }
    
                    return false;
    
                    }
    
                    // 验证 token
    
                    JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
    
                    try {
    
                    DecodedJWT jwt = jwtVerifier.verify(token);
    
                    System.out.println("认证通过:");
    
                        System.out.println("过期时间:      " + jwt.getExpiresAt());
    
                    } catch (JWTVerificationException e) {
    
                    try{
    
                      JSONObject json = new JSONObject();
    
                      json.put("msg","token has expired");
    
                      json.put("code","401");
    
                      httpServletResponse.getWriter().append(json.toJSONString());
    
                      System.out.println("token已过期");
    
                    }catch (Exception ex){
    
                      ex.printStackTrace();
    
                      httpServletResponse.sendError(401);
    
                      return false;
    
                    }
    
                    return false;
    
                    }
    
                    return true;
    
                }
    
            }
    
            return true;
    
        }
    
        @Override
    
        public void postHandle(HttpServletRequest httpServletRequest,
    
                              HttpServletResponse httpServletResponse,
    
                              Object o, ModelAndView modelAndView) throws Exception {
    
        }
    
        @Override
    
        public void afterCompletion(HttpServletRequest httpServletRequest,
    
                                    HttpServletResponse httpServletResponse,
    
                                    Object o, Exception e) throws Exception {
    
        }
    }
    

    1.2 注册拦截器LoginInteceptor(com.chinasoft.config包)

    package com.chinasoft.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    
    import org.springframework.context.annotation.Bean;
    
    import org.springframework.context.annotation.Configuration;
    
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    /**
    
    * 注册拦截器
    
    */
    
    @Configuration
    
    public class WebConfigurer implements WebMvcConfigurer {
    
        @Autowired
    
        private LoginInterceptor loginHandlerInterceptor;
    
        @Override
    
        public void addInterceptors(InterceptorRegistry registry) {
    
        registry.addInterceptor(loginHandlerInterceptor)
    
            .addPathPatterns("/**");    // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
    
        }
    
        @Bean
    
        public LoginInterceptor loginHandlerInterceptor() {
    
            return new LoginInterceptor();
    
        }
    
    }
    

    1.3 在TokenServiceImpl类中创建生成Token方法(包com.chinasoft.service.impl)

    
    package com.chinasoft.service.impl;
    
    import java.util.Date;
    
    import org.springframework.stereotype.Service;
    
    import com.auth0.jwt.JWT;
    
    import com.auth0.jwt.algorithms.Algorithm;
    
    import com.chinasoft.pojo.User;
    
    import com.chinasoft.service.TokenService;
    
    @Service
    
    public class TokenServiceImpl implements TokenService{
    
    @Override
    
    public String getToken(User user) {
    
            Date start = new Date();
    
            long currentTime = System.currentTimeMillis() + 60* 60 * 1000;//一小时有效时间
    
            Date end = new Date(currentTime);
    
            String token = "";
    
            // 生成token,开始时间,结束时间
    
            token = JWT.create().withAudience(user.getUid() + "").withIssuedAt(start).withExpiresAt(end)
    
                    .sign(Algorithm.HMAC256(user.getPassword()));
    
            return token;
    
        }
    
    }
    

    1.4 跳过身份验证的注解@PassToken 和需要身份验证的注解 @UserLoginToken(包com.chinasoft.annotation)

    PassToken

    package com.chinasoft.annotation;
    
    import java.lang.annotation.ElementType;
    
    import java.lang.annotation.Retention;
    
    import java.lang.annotation.RetentionPolicy;
    
    import java.lang.annotation.Target;
    
    /**
    
    * @author :ZWQ
    
    * @version :1.0
    
    * @date :2019/10/16 - 18:44
    
    * @description :用来跳过验证的PassToken
    
    */
    
    @Target({ElementType.METHOD, ElementType.TYPE})
    
    @Retention(RetentionPolicy.RUNTIME)
    
    public @interface PassToken {
    
        boolean required() default true;
    
    }
    

    UserLoginToken

    package com.chinasoft.annotation;
    
    import java.lang.annotation.ElementType;
    
    import java.lang.annotation.Retention;
    
    import java.lang.annotation.RetentionPolicy;
    
    import java.lang.annotation.Target;
    
    /**
    
    * @author :ZWQ
    
    * @version :1.0
    
    * @date :2019/10/16 - 18:46
    
    * @description :需要登录才能进行操作的注解UserLoginToken
    
    */
    
    @Target({ElementType.METHOD, ElementType.TYPE})
    
    @Retention(RetentionPolicy.RUNTIME)
    
    public @interface UserLoginToken {
    
        boolean required() default true;
    
    }
    

    1.5 Controller中的login方法(包com.chinasoft.controller)

    import com.chinasoft.service.TokenService;
    
    import com.chinasoft.service.UserService;
    
    @Controller
    
    @RequestMapping("user")
    
    @CrossOrigin
    
    public class UserController {
    
    @Autowired
    
    UserService service;
    
    @Autowired
    
        TokenService tokenService;
    
    // 登录(需要账号密码)
    
    @RequestMapping("login")
    
    @ResponseBody
    
    public Map login(String name, String password, HttpServletRequest request, HttpServletResponse response) {
    
    Map<String,Object> hm = new HashMap<>();    // 通过map返回token和user
    
    User user = service.LoginUser(name, password);    // Service类中的方法验证并获取用户
    
    hm.put("user", user);
    
    if (user == null) {
    
    System.out.println("该用户不存在");
    
    return null;
    
    } else {
    
    System.out.println("登录成功");
    
    }
    
    // 生成token并返回
    
    String token = tokenService.getToken(user);
    
    hm.put("token", token);
    
    return hm;
    
    }
    
    }
    

    2. 前端Vue代码实现

    相关文章

      网友评论

          本文标题:前后端分离JWT Token登录,后端Springboot代码

          本文链接:https://www.haomeiwen.com/subject/rutotltx.html