前后端分离jwt登录验证

比眉伴天荒 2022-09-03 12:25 163阅读 0赞

前后端分离jwt登录验证 (vue + springboot)

方案

  • 第一次登录后,前端j将后端返回的token保存在localStorage中
  • 以后每次前端访问后端接口时,都从localStorage中取出token加入请求header的Authorization字段
  • 后端建立拦截器,拦截每个请求的header中的Authorization字段值,即token,校验token是否过期,如果过期返回响应码401,否则放行
  • 前端建立全局响应拦截器,如果拦截到接口请求响应码是401,就跳转到登录页面

login页面

  • 登录成功保存token到localStorage

    methods: {

    1. login() {
    2. this.axios.post("/user/login", { username: this.username, password: this.password}).then((response) => {
    3. if (response.data.success) {
    4. localStorage.setItem("token", response.data.msg)
    5. this.$router.push("/xxx")
    6. } else {
    7. this.$message.error(response.data.msg)
    8. }
    9. }).catch((error) => {
    10. this.$message.error(error)
    11. })
    12. }

    },

后端接口拦截器

  1. package com.gitee.freakchicken.dbapi.conf;
  2. import com.gitee.freakchicken.dbapi.service.UserService;
  3. import com.gitee.freakchicken.dbapi.domain.User;
  4. import com.gitee.freakchicken.dbapi.util.JwtUtils;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.http.HttpMethod;
  8. import org.springframework.stereotype.Component;
  9. import org.springframework.web.method.HandlerMethod;
  10. import org.springframework.web.servlet.HandlerInterceptor;
  11. import org.springframework.web.servlet.ModelAndView;
  12. import javax.servlet.http.HttpServletRequest;
  13. import javax.servlet.http.HttpServletResponse;
  14. import java.io.PrintWriter;
  15. @Component
  16. @Slf4j
  17. public class JwtAuthenticationInterceptor implements HandlerInterceptor {
  18. @Autowired
  19. UserService userService;
  20. @Override
  21. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
  22. log.debug(request.getServletPath());
  23. // 跨域的预检请求直接放行
  24. if (request.getMethod().equals(HttpMethod.OPTIONS)) {
  25. return true;
  26. }
  27. // 如果不是映射到方法直接通过
  28. if (!(object instanceof HandlerMethod)) {
  29. return true;
  30. }
  31. PrintWriter writer = null;
  32. try {
  33. response.setCharacterEncoding("UTF-8");
  34. response.setContentType("application/json; charset=utf-8");
  35. String token = request.getHeader("Authorization");
  36. // 执行认证
  37. if (token == null) {
  38. response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
  39. writer = response.getWriter();
  40. writer.append("\"无token,请重新登录\"");
  41. return false;
  42. }
  43. // 获取 token 中的 userId
  44. String userId = JwtUtils.getAudience(token);
  45. User user = userService.getUserById(Integer.valueOf(userId));
  46. if (user == null) {
  47. response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
  48. writer = response.getWriter();
  49. writer.append("用户不存在,请重新登录");
  50. return false;
  51. }
  52. // 验证 token
  53. boolean b = JwtUtils.verifyToken(token, user.getPassword());
  54. if (b) {
  55. return true;
  56. } else {
  57. response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
  58. writer = response.getWriter();
  59. writer.append("token无效,请重新登录");
  60. return false;
  61. }
  62. } catch (Exception e) {
  63. e.printStackTrace();
  64. return false;
  65. } finally {
  66. if (writer != null) {
  67. writer.close();
  68. }
  69. }
  70. }
  71. @Override
  72. public void postHandle(HttpServletRequest request, HttpServletResponse response,
  73. Object o, ModelAndView modelAndView) throws Exception {
  74. }
  75. @Override
  76. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
  77. }
  78. }

前端main.js

  1. axios.interceptors.request.use(config => {
  2. //拦截所有请求,添加登陆用户的token
  3. if (localStorage.getItem('token')) {
  4. config.headers.Authorization = localStorage.getItem('token');
  5. }
  6. return config
  7. })
  8. //后台用户登陆信息校验不成功就跳转到登录页面
  9. axios.interceptors.response.use(response => {
  10. return response
  11. }, error => {
  12. debugger
  13. if (error.response.status == '401') {
  14. router.push("/login");
  15. } else {
  16. return Promise.reject(error)
  17. }
  18. })

后端登录方法

  1. @RequestMapping("/login")
  2. public ResponseDto login(String username, String password) {
  3. User user = userService.getUser(username, password);
  4. if (user == null) {
  5. return ResponseDto.fail("用户名或者密码错误");
  6. } else {
  7. String token = JwtUtils.createToken(user.getId().toString(), user.getPassword());
  8. return ResponseDto.successWithMsg(token);
  9. }
  10. }

附:jwt工具

  1. package com.gitee.freakchicken.dbapi.util;
  2. import com.auth0.jwt.JWT;
  3. import com.auth0.jwt.JWTVerifier;
  4. import com.auth0.jwt.algorithms.Algorithm;
  5. import com.auth0.jwt.exceptions.JWTDecodeException;
  6. import com.auth0.jwt.exceptions.JWTVerificationException;
  7. import com.auth0.jwt.interfaces.Claim;
  8. import lombok.extern.slf4j.Slf4j;
  9. import java.util.Calendar;
  10. import java.util.Date;
  11. @Slf4j
  12. public class JwtUtils {
  13. public static String createToken(String userId, String secret) {
  14. Calendar nowTime = Calendar.getInstance();
  15. nowTime.add(Calendar.SECOND, 10);
  16. Date expiresDate = nowTime.getTime();
  17. return JWT.create().withAudience(userId) //签发对象
  18. .withIssuedAt(new Date()) //发行时间
  19. .withExpiresAt(expiresDate) //有效时间
  20. .sign(Algorithm.HMAC256(secret)); //加密
  21. }
  22. /** * 检验合法性,其中secret参数就应该传入的是用户的id * * @param token */
  23. public static boolean verifyToken(String token, String secret) {
  24. JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(secret)).build();
  25. try {
  26. jwtVerifier.verify(token);
  27. return true;
  28. } catch (JWTVerificationException e) {
  29. log.error(e.getMessage());
  30. return false;
  31. }
  32. }
  33. /** * 获取签发对象 */
  34. public static String getAudience(String token) {
  35. String audience = null;
  36. try {
  37. audience = JWT.decode(token).getAudience().get(0);
  38. } catch (JWTDecodeException j) {
  39. }
  40. return audience;
  41. }
  42. /** * 通过载荷名字获取载荷的值 */
  43. public static Claim getClaimByName(String token, String name) {
  44. return JWT.decode(token).getClaim(name);
  45. }
  46. }
  47. <dependency>
  48. <groupId>com.auth0</groupId>
  49. <artifactId>java-jwt</artifactId>
  50. <version>3.8.3</version>
  51. </dependency>

发表评论

表情:
评论列表 (有 0 条评论,163人围观)

还没有评论,来说两句吧...

相关阅读