带你快速了解原理并使用

Posted 阿呆攻防

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带你快速了解原理并使用相关的知识,希望对你有一定的参考价值。

SpringBoot整合jwt

登录功能的实现

  • 登陆页面输入用户名密码进行登录

  • 服务器验证用户生成该用户Token返回客户端

  • 客户端存储该Token

  • 后续客户端的所有请求携带该Token

  • 服务器验证Token是否通过


实现原理


Session、Cookie、Token的使用状况

  • http是无状态的
  • 通过cookie在客户端记录状态
  • 通过session在服务器端记录状态
  • 通过token方式维持状态

使用条件

在同一个服务器中常用Cookie,有跨域问题时使用Token

实践测试

生成Token给客户端

pojo

@Data
public class User 
    private String username;
    private String pwd;
    private String token;


JwtUtil

public class JwtUtil 
    private static long time=1000*60*60*24;
    private static String signature="admimn";
    public static String createToken()
        JwtBuilder jwtBuilder= Jwts.builder();
        String jwtToken=jwtBuilder
                //header
                .setHeaderParam("typ","JWT")
                .setHeaderParam("alg","HS256")
                //payload
                .claim("username","admin")
                .claim("role","123456")
                .setSubject("admin-test")
                .setExpiration(new Date(System.currentTimeMillis()+time))
                .setId(UUID.randomUUID().toString())
                //signature
                .signWith(SignatureAlgorithm.HS256,signature)
                .compact();
        return jwtToken;
    


Controller

@RestController
public class UserController 
    private final String  USERNAME="admin";
    private final String PASSWORD="123456";

    @GetMapping("/login")
    public User login(User user)
        System.out.println(user);
        if(USERNAME.equals(user.getUsername()) && PASSWORD.equals(user.getPwd()))
            //添加token
            user.setToken(JwtUtil.createToken());
            return user;
        
        return null;
    


解决跨域问题

@Configuration
public class CrosConfiguration implements WebMvcConfigurer 

    @Override
    public void addCorsMappings(CorsRegistry registry)
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    


Vue

<template>
  <div class="about">
    <button @click="clickTo()">提交测试</button>
  </div>
</template>
<script>
	const axios = require('axios');
	export default
		name:'about',
		data()
			return
				user:
					username:'admin',
					pwd:'123456',
				
			
		,
		methods:
			clickTo()
				var _this=this;
				axios.get("http://localhost:8080/login",params:_this.user)
				.then(res=>
					console.log(res.data)
					//登陆成功
					if(res.data!=null)
            //存入localStorage
						localStorage.setItem('access-admin',JSON.stringify(res.data));
            //注意是router非route
						_this.$router.replace(path:'/')
					
				)
			
		
	
</script>

验证

查看存储到了localStorage对象中

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
	<p>user</p>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default 
  name: 'Home',
  components: 
    HelloWorld
  ,
  data()
	  return
		  user:""
	  
  ,
  created()
		  this.user=localStorage.getItem('access-admin');
  

</script>


客户端存储Token

在route路由中实现存储代码复用,在每一次路由跳转前都需要进行一次用户验证

router.js

//首先引入axios包
import axios from 'axios'

//然后在实例化的router后面跟执行路由的逻辑
//在进行任何一个跳转之前,都要进行验证是否登陆或者验证token是否合法
router.beforeEach((to,from,next)=>
	if(to.path.startsWith('/login'))
		window.localStorage.removeItem('access-admin');
		next();
	else
		//判断是否登陆
		let admin = JSON.parse(window.localStorage.getItem('access-admin'));
		//没登陆的用户就去登陆
		if(!admin)
			next(path:'/login');
		else
			//登陆的用户就去校验token的合法性
			axios(
				url:'http://localhost:8080/checkToken',
				method:'get',
				headers:
					token: admin.token
				
			).then((response)=>
				if(!response.data)
					console.log('校验失败')
					next(path:'/error')
				else
          //如果说正确的话,直接路由跳转
					next();
        
			)
		
	
)

Error.vue

<template>
	<div>
		1231
	</div>
</template>

<script>
	export default
		name:"Error",
		created()
			console.log("error")
				localStorage.removeItem('access-admin');
				this.$router.replace(path:'/about');
		
		
	
</script>

<style>
</style>

JwtUtil.java

在工具类中加入解析方法,验证token的合法性

public static boolean checkToken(String token)    if(token == null)        return false;        //正常就是正常解析,抛异常就是解析失败    try        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signature).parseClaimsJws(token);    catch (Exception e)        return false;        return true;

UserController.java

@GetMapping("/checkToken")public Boolean checkToken(HttpServletRequest request)    String token=request.getHeader("token");    return JwtUtil.checkToken(token);

运行效果

所有的其他路径都被/login所替代拦截

专业解读

  • 路由守卫只管有没有Token
  • 验证Token一般放在请求拦截里
  • 理论上所有的接口都有校验Token

以上是关于带你快速了解原理并使用的主要内容,如果未能解决你的问题,请参考以下文章

一文带你快速了解 Spark 架构设计与原理思想

带你快速了解 Docker 和 Kubernetes

带你快速了解 Docker 和 Kubernetes

一文带你快速了解 Java 线上问题快速诊断神器 Arthas

一文带你快速了解 Java 线上问题快速诊断神器 Arthas

一文带你了解数仓智能运维框架