JWT是什么
JSON Web Token (JWT),它是目前最流行的跨域身份验证解决方案
为什么使用JWT
JWT的精髓在于:“去中心化”,数据是保存在客户端的。
JWT的工作原理
- 是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户,示例如下:
{“UserName”: “Chongchong”,“Role”: “Admin”,“Expire”: “2018-08-08 20:15:56”}
2.之后,当用户与服务器通信时,客户在请求中发回JSON对象
3.为了防止用户篡改数据,服务器将在生成对象时添加签名,并对发回的数据进行验证
Jwt解决前后端分离资源保护问题
图解:
代码演示:
后端
UserAction
登录方法请求Java后端的一段代码,生成一个token令牌
public String login() {
ObjectMapper om = new ObjectMapper();
JsonData jsonData = null;
try {
if(StringUtils.isBlank(user.getUname()) || StringUtils.isBlank(user.getPwd())) {
jsonData = new JsonData(0, "用户或者密码为空", user);
}else {
User u = this.userBiz.login(user);
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("uname",user.getUname());
claims.put("pwd", user.getPwd());
String jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL);
response.setHeader(JwtUtils.JWT_HEADER_KEY, jwt);
jsonData = new JsonData(1, "登录成功", u);
}
} catch (Exception e) {
e.printStackTrace();
jsonData = new JsonData(0, "用户或者密码错误", user);
}finally {
try {
ResponseUtil.write(response, om.writeValueAsString(jsonData));
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
CorsFilter
前端的http.js跨域攻击
默认情况下responseHeaders是不能添加jwt的键值对信息需要手动添加
package com.zxp.vue.util;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 配置tomcat允许跨域访问
*
* @author Administrator
*
*/
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
// @Override
// public void doFilter(ServletRequest servletRequest, ServletResponse
// servletResponse, FilterChain filterChain)
// throws IOException, ServletException {
// HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
//
// // Access-Control-Allow-Origin就是我们需要设置的域名
// // Access-Control-Allow-Headers跨域允许包含的头。
// // Access-Control-Allow-Methods是允许的请求方式
// httpResponse.addHeader("Access-Control-Allow-Origin", "*");// *,任何域名
// httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT,
// DELETE");
// // httpResponse.setHeader("Access-Control-Allow-Headers", "Origin,
// // X-Requested-With, Content-Type, Accept");
//
// // 允许请求头Token
// httpResponse.setHeader("Access-Control-Allow-Headers",
// "Origin,X-Requested-With, Content-Type, Accept, Token");
// HttpServletRequest req = (HttpServletRequest) servletRequest;
// System.out.println("Token=" + req.getHeader("Token"));
// if("OPTIONS".equals(req.getMethod())) {
// return;
// }
//
//
// filterChain.doFilter(servletRequest, servletResponse);
// }
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) servletResponse;
HttpServletRequest req = (HttpServletRequest) servletRequest;
// Access-Control-Allow-Origin就是我们需要设置的域名
// Access-Control-Allow-Headers跨域允许包含的头。
// Access-Control-Allow-Methods是允许的请求方式
resp.setHeader("Access-Control-Allow-Origin", "*");// *,任何域名
resp.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");
// resp.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,
// Content-Type, Accept");
// 允许客户端,发一个新的请求头jwt
resp.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With, Content-Type, Acce