JWT简介

简介

JSON Web token简称JWT, 是用于对应用程序上的用户进行身份验证的标记。也就是说, 使用 JWTS 的应用程序不再需要保存有关其用户的 cookie 或其他session数据。此特性便于可伸缩性, 同时保证应用程序的安全。

在身份验证过程中, 当用户使用其凭据成功登录时, 将返回 JSON Web token, 并且必须在本地保存 (通常在本地存储中)。每当用户要访问受保护的路由或资源 (端点) 时, 用户代理(user agent)必须连同请求一起发送 JWT, 通常在授权标头中使用Bearer schema。后端服务器接收到带有 JWT 的请求时, 首先要做的是验证token。

JWT的格式

JWT就是一个字符串,经过加密处理与校验处理的字符串,形式为:A.B.C

A由JWT头部信息header加密得到

B由JWT用到的身份验证信息json数据加密得到

C由A和B加密得到,是校验部分

怎样使用token?

可以放到HTTP请求的请求头中,通常是Authorization字段。

流程图

jwt流程图.png

JWT 实战

加入Maven jwt 依赖

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>

在application.proterties中加入配置

# 加密yan
jwt.secret=A0B1C2D3E4F5G6H7I8J9KALBMCNDOEPFQ0R1S2T3U4V5W6X7Y8Z9
# tocken 过期时间,单位秒
jwt.expire=300
# 需要认证的url,多个URL使用英文逗号,分割
jwt.authorised-urls=/apis/fis/redis/**

JwtHelper工具类

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; public class JwtHelper {

private Long EXPIRATION_TIME;

private String SECRET;

private final String TOKEN_PREFIX = "Bearer";

private final String HEADER_STRING = "Authorization";
public JwtHelper(<span class="hljs-built_in"><span class="hljs-built_in">String</span></span> secret, long expire) {
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.EXPIRATION_TIME = expire;
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.SECRET = secret;
System.out.println(<span class="hljs-string"><span class="hljs-string">"正在初始化Jwthelper,expire="</span></span>+expire);
} public JSONObject generateToken(<span class="hljs-built_in"><span class="hljs-built_in">Map</span></span>&lt;<span class="hljs-built_in"><span class="hljs-built_in">String</span></span>, <span class="hljs-built_in"><span class="hljs-built_in">Object</span></span>&gt; claims) {
Calendar c = Calendar.getInstance();
c.setTime(<span class="hljs-keyword"><span class="hljs-keyword">new</span></span> <span class="hljs-built_in"><span class="hljs-built_in">Date</span></span>());
c.add(Calendar.SECOND, EXPIRATION_TIME.intValue());
<span class="hljs-built_in"><span class="hljs-built_in">Date</span></span> d = c.getTime();
<span class="hljs-built_in"><span class="hljs-built_in">String</span></span> jwt = Jwts.builder()
.setClaims(claims)
.setExpiration(d)
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
JSONObject json = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JSONObject();
json.put(<span class="hljs-string"><span class="hljs-string">"token"</span></span>,TOKEN_PREFIX + <span class="hljs-string"><span class="hljs-string">" "</span></span> + jwt);
json.put(<span class="hljs-string"><span class="hljs-string">"token-type"</span></span>, TOKEN_PREFIX);
json.put(<span class="hljs-string"><span class="hljs-string">"expire-time"</span></span>,<span class="hljs-keyword"><span class="hljs-keyword">new</span></span> SimpleDateFormat(<span class="hljs-string"><span class="hljs-string">"yyyy-MM-dd HH:ss:mm"</span></span>).format(d) );
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> json;
} public <span class="hljs-built_in"><span class="hljs-built_in">Map</span></span>&lt;<span class="hljs-built_in"><span class="hljs-built_in">String</span></span>, <span class="hljs-built_in"><span class="hljs-built_in">Object</span></span>&gt; validateTokenAndGetClaims(HttpServletRequest request) {
<span class="hljs-built_in"><span class="hljs-built_in">String</span></span> token = request.getHeader(HEADER_STRING);
System.out.println(<span class="hljs-string"><span class="hljs-string">"token is:"</span></span>+token);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (token == <span class="hljs-literal"><span class="hljs-literal">null</span></span>) {
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-literal"><span class="hljs-literal">null</span></span>;
}
<span class="hljs-built_in"><span class="hljs-built_in">Map</span></span>&lt;<span class="hljs-built_in"><span class="hljs-built_in">String</span></span>, <span class="hljs-built_in"><span class="hljs-built_in">Object</span></span>&gt; body = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, <span class="hljs-string"><span class="hljs-string">""</span></span>))
.getBody();
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> body;
}

}

JWT过滤器JwtFilter

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
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;
import org.springframework.http.HttpStatus;
import org.springframework.util.AntPathMatcher; /**
  • JWT过滤器
  • @author 李庆海
*/

public class JwtFilter implements Filter {

private JwtHelper jwtHelper;

private List<String> urls = null;

private static final org.springframework.util.PathMatcher pathMatcher = new AntPathMatcher();

public JwtFilter(JwtHelper jwtHelper, String[] authorisedUrls) {

this.jwtHelper = jwtHelper;

urls = Arrays.asList(authorisedUrls);

}
<span class="hljs-meta"><span class="hljs-meta">@Override</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span><span class="hljs-function"> </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">init</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(FilterConfig filterConfig)</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span><span class="hljs-function"> ServletException </span></span>{
<span class="hljs-comment"><span class="hljs-comment">//SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());</span></span>
} <span class="hljs-meta"><span class="hljs-meta">@Override</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span><span class="hljs-function"> </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">doFilter</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(ServletRequest request, ServletResponse response, FilterChain chain)</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span><span class="hljs-function"> IOException, ServletException </span></span>{
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setCharacterEncoding(<span class="hljs-string"><span class="hljs-string">"UTF-8"</span></span>);
httpResponse.setContentType(<span class="hljs-string"><span class="hljs-string">"application/json; charset=utf-8"</span></span>);
httpResponse.setHeader(<span class="hljs-string"><span class="hljs-string">"Access-Control-Allow-Origin"</span></span>, <span class="hljs-string"><span class="hljs-string">"*"</span></span>);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-string"><span class="hljs-string">"OPTIONS"</span></span>.equals(httpRequest.getMethod())) {
httpResponse.setStatus(HttpStatus.NO_CONTENT.value()); <span class="hljs-comment"><span class="hljs-comment">// HttpStatus.SC_NO_CONTENT = 204</span></span>
httpResponse.setHeader(<span class="hljs-string"><span class="hljs-string">"Access-Control-Allow-Credentials"</span></span>, <span class="hljs-string"><span class="hljs-string">"true"</span></span>);
httpResponse.setHeader(<span class="hljs-string"><span class="hljs-string">"Access-Control-Allow-Headers"</span></span>, <span class="hljs-string"><span class="hljs-string">"Content-Type, x-requested-with, Token"</span></span>);
httpResponse.setHeader(<span class="hljs-string"><span class="hljs-string">"Access-Control-Allow-Methods"</span></span>, <span class="hljs-string"><span class="hljs-string">"OPTIONS,GET,POST,DELETE,PUT"</span></span>);
}
String spath = httpRequest.getServletPath();
<span class="hljs-keyword"><span class="hljs-keyword">try</span></span> {
<span class="hljs-comment"><span class="hljs-comment">// 验证受保护的接口</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">for</span></span> (String url : urls) {
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (pathMatcher.match(url, spath)) {
Object token = jwtHelper.validateTokenAndGetClaims(httpRequest);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (token != <span class="hljs-keyword"><span class="hljs-keyword">null</span></span>) {
chain.doFilter(request, response);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
}<span class="hljs-keyword"><span class="hljs-keyword">else</span></span>{
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, <span class="hljs-string"><span class="hljs-string">"未授权或者授权已经过期"</span></span>);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
}
}<span class="hljs-keyword"><span class="hljs-keyword">else</span></span>{
chain.doFilter(request, response);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
}
}
} <span class="hljs-keyword"><span class="hljs-keyword">catch</span></span> (Exception e) {
e.printStackTrace();
}
chain.doFilter(request, response);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>;
} <span class="hljs-meta"><span class="hljs-meta">@Override</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">void</span></span></span><span class="hljs-function"> </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">destroy</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">()</span></span></span><span class="hljs-function"> </span></span>{ }

}

配置JWT

import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import cn.com.yd.fis.client.jwt.JwtFilter;

import cn.com.yd.fis.client.jwt.JwtHelper; @Configuration

public class JwtConfig {
<span class="hljs-meta"><span class="hljs-meta">@Value</span></span>(<span class="hljs-string"><span class="hljs-string">"${jwt.secret}"</span></span>)
<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> String secret; <span class="hljs-meta"><span class="hljs-meta">@Value</span></span>(<span class="hljs-string"><span class="hljs-string">"${jwt.expire}"</span></span>)
<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> <span class="hljs-keyword"><span class="hljs-keyword">long</span></span> expire; <span class="hljs-meta"><span class="hljs-meta">@Value</span></span>(<span class="hljs-string"><span class="hljs-string">"${jwt.authorised-urls}"</span></span>)
<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> String[] authorisedUrls; <span class="hljs-meta"><span class="hljs-meta">@Bean</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> JwtHelper </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">jwtHelperBean</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">()</span></span></span><span class="hljs-function"> </span></span>{
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JwtHelper(secret, expire);
} <span class="hljs-meta"><span class="hljs-meta">@Bean</span></span>
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> FilterRegistrationBean </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">basicFilterRegistrationBean</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">()</span></span></span><span class="hljs-function"> </span></span>{
FilterRegistrationBean registrationBean = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> FilterRegistrationBean();
JwtFilter filter = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JwtFilter(jwtHelperBean(), authorisedUrls);
registrationBean.setFilter(filter);
List&lt;String&gt; urlPatterns = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> ArrayList&lt;String&gt;();
urlPatterns.add(<span class="hljs-string"><span class="hljs-string">"/*"</span></span>);
registrationBean.setUrlPatterns(urlPatterns);
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> registrationBean;
}

}

在Controller中使用JWT

此处仅为说明jwt的用法,在实际应用时可以根据具体的业务需要加入不同的或者更多的参数,一并作为claims进行参数传递。

import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import cn.com.yd.fis.client.jwt.JwtHelper;
import cn.com.yd.fis.client.util.JsonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; @RestController

@RequestMapping("${api-url}/auth")

public class AuthorizeController {
<span class="hljs-meta"><span class="hljs-meta">@Autowired</span></span>
<span class="hljs-keyword"><span class="hljs-keyword">private</span></span> JwtHelper jwtHelper; <span class="hljs-meta"><span class="hljs-meta">@PostMapping</span></span>(<span class="hljs-string"><span class="hljs-string">"/login"</span></span>)
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> Object </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">login</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(String loginName,String password)</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">throws</span></span></span><span class="hljs-function"> Exception </span></span>{
Map&lt;String, Object&gt; claims = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> HashMap&lt;String, Object&gt;();
claims.put(<span class="hljs-string"><span class="hljs-string">"loginName"</span></span>, loginName);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-string"><span class="hljs-string">"1"</span></span>.equals(password)) {
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> JsonResult.success(jwtHelper.generateToken(claims));
} <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> {
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> JsonResult.fail(<span class="hljs-string"><span class="hljs-string">"登录帐号或者登录密码错误"</span></span>);
}
}

}

辅助工具类JsonResult

import com.alibaba.fastjson.JSONObject;

public class JsonResult {

public static JSONObject success(Object obj) {

JSONObject json = new JSONObject();

json.put("state", true);

json.put("msg", "成功");

if (null != obj) {

json.put("obj", obj);

}

return json;

}
<span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">static</span></span></span><span class="hljs-function"> JSONObject </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">fail</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(Object obj)</span></span></span><span class="hljs-function"> </span></span>{
JSONObject json = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JSONObject();
json.put(<span class="hljs-string"><span class="hljs-string">"state"</span></span>, <span class="hljs-keyword"><span class="hljs-keyword">false</span></span>);
json.put(<span class="hljs-string"><span class="hljs-string">"msg"</span></span>, <span class="hljs-string"><span class="hljs-string">"失败"</span></span>);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">null</span></span> != obj) {
json.put(<span class="hljs-string"><span class="hljs-string">"obj"</span></span>, obj);
}
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> json;
} <span class="hljs-function"><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">public</span></span></span><span class="hljs-function"> </span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-keyword">static</span></span></span><span class="hljs-function"> JSONObject </span><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">toJSONObject</span></span></span><span class="hljs-params"><span class="hljs-function"><span class="hljs-params">(</span></span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params"><span class="hljs-keyword">boolean</span></span></span></span><span class="hljs-function"><span class="hljs-params"> state, String msg, Object obj)</span></span></span><span class="hljs-function"> </span></span>{
JSONObject json = <span class="hljs-keyword"><span class="hljs-keyword">new</span></span> JSONObject();
json.put(<span class="hljs-string"><span class="hljs-string">"state"</span></span>, state);
json.put(<span class="hljs-string"><span class="hljs-string">"msg"</span></span>, msg);
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (<span class="hljs-keyword"><span class="hljs-keyword">null</span></span> != obj) {
json.put(<span class="hljs-string"><span class="hljs-string">"obj"</span></span>, obj);
}
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> json;
}

}

原文地址:https://www.jianshu.com/p/620a9b15a619

最新文章

  1. SQL Server中CROSS APPLY和OUTER APPLY的应用详解
  2. django 1.7之后python manage.py syncdb没有了
  3. 汇编学习(四)&mdash;&mdash;算术运算程序
  4. maven中的 dependencies 和 dependencyManagement 的区别
  5. iOS - OC NSPoint 位置
  6. java小程序 质数
  7. git 仓库操作
  8. cetos 7 常用命令
  9. (转载)php循环检测目录是否存在并创建(循环创建目录)
  10. 关于Zend Framework 2中 Zend\Session的使用
  11. JavaScript获取某年某月的最后一天
  12. 用ul、li做横向导航
  13. python __name__ 变量的含义
  14. 自学spring AOP
  15. 重绘(redraw或repaint),重排(reflow)
  16. uniq命令
  17. Vue2+VueRouter2+webpack 构建项目实战(二):目录以及文件结构
  18. Java数组常用方法
  19. linux POSIX 信号量介绍
  20. layui 3种导航栏

热门文章

  1. RHEL7系统安装方式
  2. python基础--常用的模块(collections、time、datetime、random、os、sys、json、pickle)
  3. 洛谷P1474 [USACO 2.3]货币系统 Money Systems [2017年4月计划 动态规划04]
  4. Leetcode71. Simplify Path简化路径
  5. android中的http框架,使其更加简单易用
  6. ACdream 1101 线段树
  7. 访问Bing地图
  8. 【JZOJ5081】【GDSOI2017第三轮模拟】Travel Plan 背包问题+双指针+树的dfs序
  9. 用蒙特卡罗方法解非线性规划MATLAB
  10. LeetCode141 Linked List Cycle. LeetCode142 Linked List Cycle II