什么是jwt?

最详细的是官网:https://jwt.io/

这里以java的ssm框架为例,集成jwt。

1.pom.xml 导入jwt的包

 <!-- jwt -->
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>2.2.0</version>
</dependency>

jwt的工具类,有加密解密功能就好

import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap;
import java.util.Map; public class JWT {
private static final String SECRET = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW"; private static final String EXP = "exp"; private static final String PAYLOAD = "payload"; //加密,传入一个对象和有效期
public static <T> String sign(T object, long maxAge) {
try {
final JWTSigner signer = new JWTSigner(SECRET);
final Map<String, Object> claims = new HashMap<String, Object>();
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(object);
claims.put(PAYLOAD, jsonString);
claims.put(EXP, System.currentTimeMillis() + maxAge);
return signer.sign(claims);
} catch(Exception e) {
return null;
}
} //解密,传入一个加密后的token字符串和解密后的类型
public static<T> T unsign(String jwt, Class<T> classT) {
final JWTVerifier verifier = new JWTVerifier(SECRET);
try {
final Map<String,Object> claims= verifier.verify(jwt);
if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
long exp = (Long)claims.get(EXP);
long currentTimeMillis = System.currentTimeMillis();
if (exp > currentTimeMillis) {
String json = (String)claims.get(PAYLOAD);
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, classT);
}
}
return null;
} catch (Exception e) {
return null;
}
} }

3.jwt有了,ssm要如何去利用,用户验证的第一步是登录,登录时根据用户传来的username和password到数据库验证身份,如果合法,便给该用户jwt加密生成token

//处理登录
@RequestMapping(value="login", produces = "application/json; charset=utf-8")
public @ResponseBody ResponseData login(HttpServletRequest request, @RequestParam( "email") String email,
@RequestParam("password") String password) {
Login login = new Login();
login.setEmail(email);
login.setPassword(password);
ResponseData responseData = ResponseData.ok();
//先到数据库验证
Integer loginId = userService.checkLogin(login);
if(null != loginId) {
User user = userService.getUserByLoginId(loginId);
login.setId(loginId);
//给用户jwt加密生成token
String token = JWT.sign(login, 60L* 1000L* 30L);
//封装成对象返回给客户端
responseData.putDataValue("loginId", login.getId());
responseData.putDataValue("token", token);
responseData.putDataValue("user", user);
}
else{
responseData = ResponseData.customerError();
}
return responseData;
}

4.在用户登录时,把loginId和token返回给前台,以后用户每次请求时,都得带上这两个参数,后台拿到token后解密出loginId,与用户传递过来的loginId比较,如果相同,则说明用户身份合法。因为是每个登录过后的每个请求,这里用springmvc的拦截器做

<mvc:interceptors>
<mvc:interceptor>
<!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
<mvc:mapping path="/**" />
<!-- /register 和 /login 不需要拦截-->
<mvc:exclude-mapping path="/register" />
<mvc:exclude-mapping path="/login" />
<bean class="com.xforce.charles.interceptor.TokenInterceptor"></bean>
</mvc:interceptor>
<!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
</mvc:interceptors>

5.拦截器代码

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import com.alibaba.fastjson.JSONObject;
import com.xforce.charles.model.Admin;
import com.xforce.charles.model.Login;
import com.xforce.charles.util.JWT;
import com.xforce.charles.util.ResponseData; public class TokenInterceptor implements HandlerInterceptor{ public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception arg3)
throws Exception {
} public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView model) throws Exception {
} //拦截每个请求
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
response.setCharacterEncoding("utf-8");
String token = request.getParameter("token");
ResponseData responseData = ResponseData.ok();
//token不存在
if(null != token) {
Login login = JWT.unsign(token, Login.class);
String loginId = request.getParameter("loginId");
//解密token后的loginId与用户传来的loginId不一致,一般都是token过期
if(null != loginId && null != login) {
if(Integer.parseInt(loginId) == login.getId()) {
return true;
}
else{
responseData = ResponseData.forbidden();
responseMessage(response, response.getWriter(), responseData);
return false;
}
}
else
{
responseData = ResponseData.forbidden();
responseMessage(response, response.getWriter(), responseData);
return false;
}
}
else
{
responseData = ResponseData.forbidden();
responseMessage(response, response.getWriter(), responseData);
return false;
}
} //请求不通过,返回错误信息给客户端
private void responseMessage(HttpServletResponse response, PrintWriter out, ResponseData responseData) {
responseData = ResponseData.forbidden();
response.setContentType("application/json; charset=utf-8");
String json = JSONObject.toJSONString(responseData);
out.print(json);
out.flush();
out.close();
} }

6.注意点:用@ResponseBody返回json数据时,有时会有乱码,需要在springmvc的配置文件里面加以下配置(spring4以上)

<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

7.最后分享一个类,用于返回给客户端的万能类,我觉得它可以满足一般的接口

import java.util.HashMap;
import java.util.Map; public class ResponseData { private final String message;
private final int code;
private final Map<String, Object> data = new HashMap<String, Object>(); public String getMessage() {
return message;
} public int getCode() {
return code;
} public Map<String, Object> getData() {
return data;
} public ResponseData putDataValue(String key, Object value) {
data.put(key, value);
return this;
} private ResponseData(int code, String message) {
this.code = code;
this.message = message;
} public static ResponseData ok() {
return new ResponseData(200, "Ok");
} public static ResponseData notFound() {
return new ResponseData(404, "Not Found");
} public static ResponseData badRequest() {
return new ResponseData(400, "Bad Request");
} public static ResponseData forbidden() {
return new ResponseData(403, "Forbidden");
} public static ResponseData unauthorized() {
return new ResponseData(401, "unauthorized");
} public static ResponseData serverInternalError() {
return new ResponseData(500, "Server Internal Error");
} public static ResponseData customerError() {
return new ResponseData(1001, "customer Error");
}
}

基于JAVA JWT 实现OATUH TOKEN验证的更多相关文章

  1. Java JWT: JSON Web Token

    Java JWT: JSON Web Token for Java and Android JJWT aims to be the easiest to use and understand libr ...

  2. 【JWT】JWT+HA256加密 Token验证

    目录 Token验证 传统的Token验证 JWT+HA256验证 回到顶部 Token验证 最近了解下基于 Token 的身份验证,跟大伙分享下.很多大型网站也都在用,比如 Facebook,Twi ...

  3. 简易 Token 验证的实现

    简易 Token 验证的实现 前言 在我们的服务器和客户端的交互中,由于我们的业务中使用 RESTful API 的形式和客户端交互,而 API 又是无状态的,无法帮助我们识别这一次和上一次的请求由谁 ...

  4. 基于jwt的token验证

    一.什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). 该token被设计为紧凑且安全的,特别适用于分布 ...

  5. 基于JWT实现token验证

    JWT的介绍 Json Web Token(JWT)是目前比较流行的跨域认证解决方案,是一种基于JSON的开发标准,由于数据是可以经过签名加密的,比较安全可靠,一般用于前端和服务器之间传递信息,也可以 ...

  6. 带领技术小白入门——基于java的微信公众号开发(包括服务器配置、java web项目搭建、tomcat手动发布web项目、微信开发所需的url和token验证)

    微信公众号对于每个人来说都不陌生,但是许多人都不清楚是怎么开发的.身为技术小白的我,在闲暇之余研究了一下基于java的微信公众号开发.下面就是我的实现步骤,写的略显粗糙,希望大家多多提议! 一.申请服 ...

  7. Asp.Net Core 3.1 学习3、Web Api 中基于JWT的token验证及Swagger使用

    1.初始JWT 1.1.JWT原理 JWT(JSON Web Token)是目前最流行的跨域身份验证解决方案,他的优势就在于服务器不用存token便于分布式开发,给APP提供数据用于前后端分离的项目. ...

  8. SpringBoot集成JWT实现token验证

    原文:https://www.jianshu.com/p/e88d3f8151db JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github. ...

  9. 前端和后端采用接口访问时的调用验证机制(基于JWT的前后端验证)(思路探讨)

    说明:基于前后端,尤其是使用Ajax请求的接口,现在市面上网页上调用的Ajax基本都是没有验证的,如果单独提取之后可以无线的刷数据. 继上一篇http://www.cnblogs.com/EasonJ ...

随机推荐

  1. PL/SQL复合类型

    一.PL/SQL记录:一条记录. 可简化单行多列的数据的处理.当使用pl/sql记录时,应用开发人员即可以自定义记录类型和记录变量,也可以使用%rowtype属性直接定义记录变量. 1.当使用自定义的 ...

  2. MySQL之表连接-> 内连接,左外连接,右外链接,全连接

    1.首先创建student库 create database student; 2. 在数据库中创建boy表 和 girl表, mysql> create table boy( -> bo ...

  3. MOS管做开关之初理解

    杰杰 物联网IoT开发 2017-10-12 大家好,我是杰杰.       今晚,设计电路搞了一晚上,终于从模电渣渣的我,把MOS管理解了那么一丢丢,如有写的不好的地方,请指出来.谢谢.      ...

  4. The 2019 China Collegiate Programming Contest Harbin Site F. Fixing Banners

    链接: https://codeforces.com/gym/102394/problem/F 题意: Harbin, whose name was originally a Manchu word ...

  5. linux其他

    1.安装上传下载指令 sz/rz yum install -y lrzsz 2.flask+gunicorn 代码更新升级部署 ps -ef | grep gunicorn 获取master进程 ki ...

  6. 使用 ServerSocket 建立聊天服务器-1

    1.代码目录 2.ChatSocket.java --------------------------------------------------------------------------- ...

  7. tsnr--基于vpp+dpdk的高性能防火墙

    tsnr--基于vpp+dpdk的高性能防火墙 2019年01月31日 12:06:00 网络安全研发随想 阅读数:508   版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...

  8. Python数据类型解析(基础篇)

    Python语言的类型   数字类型   字符串类型   元组类型   列表类型   文件类型  字典类型     1.数字类型   Python有三种数字类型:整数,浮点数,复数 Python中的整 ...

  9. python版本下载时时,官方目录web-based与executable和embeddable 的区别

    背景:安装python时不知道选择哪个版本以及他们之间的意思. 1.X86和X86-64的区别:系統是32 bit 的版本还是 64bit 的 2.web-based ,executable , em ...

  10. [bzoj 2768]&[bzoj 1877]

    传送门1 传送门1 Solution 两道比较裸的题... 复习一下最大流和费用流的模板. Code[bzoj 2768][JLOI 2010] 冠军调查 #include<bits/stdc+ ...