springboot使用Jwt处理跨域认证问题
在前后端开发时为什么需要用户认证呢?原因是由于HTTP协定是不存储状态的,这意味着当我们透过账号密码验证一个使用者时,当下一个request请求时他就把刚刚的资料忘记了。于是我们的程序就不知道谁是谁了。 所以为了保证系统的安全,就需要验证用户是否处于登陆状态。
一、JWT的组成
JWT由Header、Payload、Signature三部分组成,分别用.分隔。
下面就是一个jwt真实的样子,说白了就是一个字符串,但是里面却存储了很重要的信息。
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJyYXljaGVuIiwiaWQiOjIsIm5hbWUiOiJyYXkiLCJwYXNzd29yZCI6IjMyMSIsImlhdCI6MTU5MDI5OTU0OCwiZXhwIjoxNTkwMzg1OTQ4fQ.ORJNldDIfffg7D3_xu0_dBWb16y4fPLtw_r6qgScFpQ
Header:
第一部分是请求头由两部分组成,
alg与typ,第一个指定的是算法,第二指定的是类型。
Payload
第二部分是主体信息组成,用来存储
JWT基本信息,或者是我们的信息。
Signature
第三部分主要是给第一部分跟第二部进行签名使用的,用来验证是否是我们服务器发起的
Token,secret是我们的密钥。
二、在springboot项目中使用jwt做验证
具体流程:
- 把用户的用户名和密码发到后端
- 后端进行校验,校验成功会生成token, 把token发送给客户端
- 客户端自己保存token, 再次请求就要在Http协议的请求头中带着token去访问服务端,和在服务端保存的token信息进行比对校验。
1.先引入jar包
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2.使用工具类生成token和验证token(生成token方法中存入了用户的信息)
public class JwtUtils {
//发行者
public static final String SUBJECT="raychen";
//过期时间 一天
public static final long EXPIRE=1000*60*60*24;
//密钥
public static final String APPSECRET="raychen11";
/**
* 生成jwt
* @param user
* @return
*/
public static String geneJsonWebToken(User user){
if(user==null || user.getId()==null || user.getName()==null || user.getPassword()==null){
return null;
}
String token=Jwts.builder().setSubject(SUBJECT)
.claim("id",user.getId())
.claim("name",user.getName())
.claim("password",user.getPassword())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis()+EXPIRE))
.signWith(SignatureAlgorithm.HS256,APPSECRET).compact();
return token;
}
/**
* 校验token
* @param token
* @return
*/
public static Claims checkJWT(String token){
//仿造的token或者已过期就会报错
try {
final Claims claims=Jwts.parser().setSigningKey(APPSECRET).parseClaimsJws(token).getBody();
return claims;
}catch (Exception e){
System.out.println("catch...");
}
return null;
}
}
3.自定义注解(进行token验证)
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckToken {
boolean required() default true;
}
4.编写config,将后台所有请求先去拦截器(拦截器返回了true,用户才可以请求到接口)
@Configuration
public class InterceptorConfig implements WebMvcConfigurer { @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**"); // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
} @Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}
5.定义拦截器(对需要token验证的请求,进行验证,验证成功返回true,失败返回false无法请求到接口)
public class AuthenticationInterceptor implements HandlerInterceptor {
public static final Gson gson=new Gson();
/**
* 进入controller之前进行拦截
* @param request
* @param response
* @param object
* @return
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
// 如果不是映射到方法直接通过
if (!(object instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) object;
Method method = handlerMethod.getMethod();
//检查是否有LoginToken注释,有则跳过认证
if (method.isAnnotationPresent(LoginToken.class)) {
LoginToken loginToken = method.getAnnotation(LoginToken.class);
if (loginToken.required()) {
return true;
}
}
//前面是不需要token验证的 从 http 请求头中取出 token
String token = request.getHeader("token");
//检查有没有需要用户权限的注解
if (method.isAnnotationPresent(CheckToken.class)) {
CheckToken checkToken = method.getAnnotation(CheckToken.class);
if (checkToken.required()) {
if(token!=null){
Claims claims= JwtUtils.checkJWT(token);
if(null==claims){
sendJsonMessage(response, JsonData.buildError("token有误"));
return false;
}
Integer userId= (Integer) claims.get("id");
String name = (String) claims.get("name");
request.setAttribute("userId",userId);
request.setAttribute("name",name);
return true;
}
//token为null的话 返回一段json给前端
sendJsonMessage(response, JsonData.buildError("请登录"));
return false;
}
}
//没有使用注解的方法 直接返回true
return true;
}
/**
* 响应数据给前端
* @param response
* @param obj
* @throws IOException
*/
public static void sendJsonMessage (HttpServletResponse response, Object obj) throws IOException {
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print(gson.toJson(obj));
writer.close();
response.flushBuffer();
}
}
用户登录成功后,使用工具类生成token。token在服务端不做存储,直接将token返回给客户端,客户端下次请求服务端时,使用工具类来验证header里的token是否合法。
springboot使用Jwt处理跨域认证问题的更多相关文章
- JWT token 跨域认证
JSON Web Token(缩写 JWT),是目前最流行的跨域认证解决方案. session登录认证方案:用户从客户端传递用户名.密码等信息,服务端认证后将信息存储在session中,将sessio ...
- go使用JWT进行跨域认证最全教学
JWT前言 JWT是JSON Web Token的缩写.JWT本身没有定义任何技术实现,它只是定义了一种基于Token的会话管理的规则,涵盖Token需要包含的标准内容和Token的生成过程. JWT ...
- JSON Web Token(缩写 JWT) 目前最流行的跨域认证解决方案
一.跨域认证的问题 互联网服务离不开用户认证.一般流程是下面这样. 1.用户向服务器发送用户名和密码. 2.服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色.登录时间等等. ...
- Cookie、Session、Token与JWT(跨域认证)
之前看到群里有人问JWT相关的内容,只记得是token的一种,去补习了一下,和很久之前发的认证方式总结的笔记放在一起发出来吧. Cookie.Session.Token与JWT(跨域认证) 什么是Co ...
- 干掉Session?这个跨域认证解决方案真的优雅!
用户登录认证是 Web 应用中非常常见的一个业务,一般的流程是这样的: 客户端向服务器端发送用户名和密码 服务器端验证通过后,在当前会话(session)中保存相关数据,比如说登录时间.登录 IP 等 ...
- SpringBoot学习(3)-SpringBoot添加支持CORS跨域访问
SpringBoot学习(3)-SpringBoot添加支持CORS跨域访问 https://blog.csdn.net/yft_android/article/details/80307672
- 2019-03-26 SpringBoot项目部署遇到跨域问题,记录一下解决历程
近期SpringBoot项目部署遇到跨域问题,记录一下解决历程. 要严格限制,允许哪些域名访问,在application.properties文件里添加配置,配置名可以自己起: cors.allowe ...
- SpringBoot添加支持CORS跨域访问
原文:https://www.jianshu.com/p/c6ea21b64f6e CORS(Cross-Origin Resource Sharing)"跨域资源共享",是一个W ...
- Springboot vue.js html 跨域 前后分离 Activiti6 工作流 集成代码生成器 shiro 权限
官网:www.fhadmin.org 特别注意: Springboot 工作流 前后分离 + 跨域 版本 (权限控制到菜单和按钮) 后台框架:springboot2.1.2+ activiti6.0 ...
随机推荐
- 汉字编码对照表(gb2312/Big5/GB2312)
一.汉字编码的种类 1.GB2312又称国标码,由国家标准总局发布,1981年5月1日实施,通行于大陆.新加坡等地也使用此编码.它是一个简化字的编码规范,当然也包括其他的符号.字母.日文假名等,共74 ...
- material UI中withStyles和makeStyles的区别
在material UI中,withStyles和makeStyles是经常使用的两个用于封装样式的函数.对于刚使用material UI的开发者而言,可能不太清楚这两者的区别. 本文简要探究 ...
- Clickhouse 条形图📊函数展示
Clickhouse 条形图
- CF--思维练习-- CodeForces - 215C - Crosses(思维题)
ACM思维题训练集合 There is a board with a grid consisting of n rows and m columns, the rows are numbered fr ...
- 思维+模拟--POJ 1013 Counterfeit Dollar
Sally Jones has a dozen Voyageur silver dollars. However, only eleven of the coins are true silver d ...
- USACO Training Section 1.2 [USACO1.2]回文平方数
题目描述 回文数是指从左向右念和从右向左念都一样的数.如12321就是一个典型的回文数. 给定一个进制B(2<=B<=20,由十进制表示),输出所有的大于等于1小于等于300(十进制下)且 ...
- CodeForces - 1058D D. Vasya and Triangle
D. Vasya and Triangle time limit per test1 second memory limit per test256 megabytes inputstandard i ...
- postman(全局变量设置)
全局变量 全局变量作用于整个postman工具及所有环境 1.点击小齿轮进入到变量添加页面,点击Globals添加全局变量 2.输入变量名称和变量值 3.接口中设置变量 4.调用 Globals 变量 ...
- Java——Lambda表达式
一.Lambda表达式入门 我们先来看一段代码:匿名内部类的方式实现参数的传递 interface Command{ public abstract void test(); } public cla ...
- bootstrap栅格系统的使用
bootstrap栅格系统的使用 bootstrap栅格系统的使用,主要分为四种方式 1.列组合 col-md-* 2.列偏移 col-md-offset-* 3.列嵌套 大列组合包含着小组合 4 ...