没有了解过JWT可以先看看JWT基础

一、 后端

由于是demo版没有进行数据库连接

登录接口

  • 账号密码验证
  • jwt-token验证 ```java package com.jili.jwt.controller;

import com.jili.jwt.entity.User; import com.jili.jwt.util.JwtUtil; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**

  • @author: Jili
  • @date: Created on 2021/6/24 16:26 */ @RestController public class UserController {

    private final String USERNAME = “admin”; private final String PASSWORD = “123456”;

    @GetMapping(“/login”) public User login(User user){

    1. if(USERNAME.equals(user.getUsername())&&PASSWORD.equals(user.getPassword())){
    2. //添加token
    3. user.setToken(JwtUtil.createToken());
    4. return user;
    5. }
    6. return null;

    }

    @GetMapping(“/checkToken”) public Boolean checkToken(HttpServletRequest request){

    1. String token=request.getHeader("token");
    2. return JwtUtil.checkToken(token);

    }

}

  1. <a name="Oh9L7"></a>
  2. ### JWT工具类
  3. - 生成jwt
  4. - 验证jwt
  5. ```java
  6. package com.jili.jwt.util;
  7. import io.jsonwebtoken.*;
  8. import java.util.Date;
  9. import java.util.UUID;
  10. /**
  11. * @author: Jili
  12. * @date: Created on 2021/6/24 16:35
  13. */
  14. public class JwtUtil {
  15. //一天
  16. private static long time = 1000*60*60*24;
  17. //5s
  18. private static long time5s = 1000*5;
  19. private static String signature = "admin";
  20. public static String createToken() {
  21. JwtBuilder jwtBuilder= Jwts.builder();
  22. String jwtToken = jwtBuilder
  23. //Header
  24. .setHeaderParam("typ","JWT")
  25. .setHeaderParam("alg","HS256")
  26. //payload
  27. .claim("username","admin")
  28. .claim("role","admin")
  29. //payload sub主题
  30. .setSubject("admin-test")
  31. //payload 有效时间
  32. .setExpiration(new Date(System.currentTimeMillis()+time5s))
  33. .setId(UUID.randomUUID().toString())
  34. //signature
  35. .signWith(SignatureAlgorithm.HS256,signature)
  36. //拼接
  37. .compact();
  38. return jwtToken;
  39. }
  40. public static boolean checkToken(String token){
  41. if(token == null){
  42. return false;
  43. }
  44. try {
  45. Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signature).parseClaimsJws(token);
  46. } catch (Exception e) {
  47. return false;
  48. }
  49. return true;
  50. }
  51. }

跨域配置

CorsConfig

  1. package com.jili.jwt.configuration;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.cors.CorsConfiguration;
  5. import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
  6. import org.springframework.web.filter.CorsFilter;
  7. /**
  8. * @author: Jili
  9. * @date: Created on 2021/6/24 16:41
  10. * 过滤器的方式
  11. */
  12. @Configuration
  13. public class CorsConfig {
  14. private CorsConfiguration buildConfig() {
  15. //创建CorsConfiguration对象后添加配置
  16. CorsConfiguration corsConfiguration = new CorsConfiguration();
  17. //设置放行哪些原始域
  18. corsConfiguration.addAllowedOrigin("*");
  19. //放行哪些原始请求头部信息
  20. corsConfiguration.addAllowedHeader("*");
  21. //放行哪些请求方式{get,put,post,delete} "*"全部放行
  22. corsConfiguration.addAllowedMethod("*");
  23. //超时时长设置为1小时。 时间单位是秒
  24. corsConfiguration.setMaxAge(3600L);
  25. return corsConfiguration;
  26. }
  27. @Bean
  28. public CorsFilter corsFilter() {
  29. //添加映射路径
  30. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  31. source.registerCorsConfiguration("/**", buildConfig());
  32. return new CorsFilter(source);
  33. }
  34. }

二、 前端

登录账号你密码验证通过后把后端传的带有用户信息以及Token存入localStorage

登录页面

Login.vue

  1. <template>
  2. <div class="login-container">
  3. <el-form :model="ruleForm" :rules="rules"
  4. status-icon
  5. ref="ruleForm"
  6. label-position="left"
  7. label-width="0px"
  8. class="demo-ruleForm login-page">
  9. <h3 class="title">系统登录</h3>
  10. <el-form-item prop="username">
  11. <el-input type="text"
  12. v-model="ruleForm.username"
  13. auto-complete="off"
  14. placeholder="用户名"
  15. ></el-input>
  16. </el-form-item>
  17. <el-form-item prop="password">
  18. <el-input type="password"
  19. v-model="ruleForm.password"
  20. auto-complete="off"
  21. placeholder="密码"
  22. ></el-input>
  23. </el-form-item>
  24. <el-form-item style="width:100%;">
  25. <el-button type="primary" style="width:100%;" @click="handleSubmit" >登录</el-button>
  26. </el-form-item>
  27. </el-form>
  28. </div>
  29. </template>
  30. <script>
  31. export default {
  32. name: "Login",
  33. data(){
  34. return{
  35. ruleForm: {
  36. username: 'admin',
  37. password: ''
  38. },
  39. rules: {
  40. username: [{required: true, message: '请输入用户名', trigger: 'blur'}],
  41. password: [{required: true, message: '请输入密码', trigger: 'blur'}]
  42. }
  43. }
  44. },
  45. methods: {
  46. handleSubmit(){
  47. this.$refs.ruleForm.validate((valid) => {
  48. if(valid){
  49. let _this = this
  50. axios.get('http://localhost:8080/login',{params:_this.ruleForm}).then(function (response) {
  51. if(response.data!=null){
  52. localStorage.setItem('access-admin',JSON.stringify(response.data))
  53. _this.$router.replace({path:'/'})
  54. }
  55. })
  56. }else{
  57. console.log('error submit!');
  58. return false;
  59. }
  60. })
  61. }
  62. }
  63. };
  64. </script>
  65. <style scoped>
  66. .login-container {
  67. width: 100%;
  68. height: 100%;
  69. }
  70. .login-page {
  71. -webkit-border-radius: 5px;
  72. border-radius: 5px;
  73. margin: 180px auto;
  74. width: 350px;
  75. padding: 35px 35px 15px;
  76. background: #fff;
  77. border: 1px solid #eaeaea;
  78. box-shadow: 0 0 25px #cac6c6;
  79. }
  80. label.el-checkbox.rememberme {
  81. margin: 0px 0px 15px;
  82. text-align: left;
  83. }
  84. </style>

路由管理

为了避免用户没有权限或者验证过期访问其他页面,在路由里统一配置,在每个页面请求前先发送请求验证token
router->index.js

  1. router.beforeEach((to, from, next) => {
  2. if (to.path.startsWith('/login')) {
  3. window.localStorage.removeItem('access-admin')
  4. next()
  5. } else {
  6. let admin = JSON.parse(window.localStorage.getItem('access-admin'))
  7. if (!admin) {
  8. next({path: '/login'})
  9. } else {
  10. //校验token合法性
  11. axios({
  12. url:'http://localhost:8080/checkToken',
  13. method:'get',
  14. headers:{
  15. token:admin.token
  16. }
  17. }).then((response) => {
  18. console.log(response.data)
  19. if(!response.data){
  20. console.log('校验失败')
  21. next({path: '/error'})
  22. }
  23. })
  24. next()
  25. }
  26. }
  27. })

三、 效果

便于测试,这里设置的token时效为5s
登录页面
image.png
验证通过
image.png


时效内
image.png
失效过期
image.png


源码
后端:https://gitee.com/jili_lyj/jwt
前端:https://gitee.com/jili_lyj/jwt-demo