├── .classpath ├── .gitignore ├── .project ├── .settings ├── .jsdtscope ├── org.eclipse.jdt.core.prefs ├── org.eclipse.wst.common.component ├── org.eclipse.wst.common.project.facet.core.xml ├── org.eclipse.wst.jsdt.ui.superType.container └── org.eclipse.wst.jsdt.ui.superType.name ├── JWT-for-JDK6.zip ├── LICENSE ├── README.md ├── WebRoot ├── META-INF │ └── MANIFEST.MF ├── WEB-INF │ ├── .gitignore │ └── lib │ │ ├── asm-1.0-RC1.jar │ │ ├── cors-filter-2.2.1.jar │ │ ├── java-property-utils-1.9.1.jar │ │ ├── json-smart-2.0-RC2.jar │ │ └── nimbus-jose-jwt-4.13.1.jar ├── flowsheet.JPG ├── index.jsp ├── jquery-2.1.0.js ├── login.html └── main.html └── src └── com ├── filter ├── Filter0_CrossOriginResource.java └── Filter1_CheckToken.java ├── jwt ├── Jwt.java ├── JwtTestCase.java └── TokenState.java └── servlet ├── AuthorServlet.java ├── LoginServlet.java └── mainServlet.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | JWT 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.common.project.facet.core.builder 20 | 21 | 22 | 23 | 24 | org.eclipse.wst.validation.validationbuilder 25 | 26 | 27 | 28 | 29 | com.genuitec.eclipse.j2eedt.core.DeploymentDescriptorValidator 30 | 31 | 32 | 33 | 34 | com.genuitec.eclipse.ast.deploy.core.DeploymentBuilder 35 | 36 | 37 | 38 | 39 | 40 | org.eclipse.jem.workbench.JavaEMFNature 41 | org.eclipse.wst.common.modulecore.ModuleCoreNature 42 | org.eclipse.wst.common.project.facet.core.nature 43 | org.eclipse.jdt.core.javanature 44 | org.eclipse.wst.jsdt.core.jsNature 45 | 46 | 47 | -------------------------------------------------------------------------------- /.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 4 | org.eclipse.jdt.core.compiler.compliance=1.7 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 7 | org.eclipse.jdt.core.compiler.source=1.7 8 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /JWT-for-JDK6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigmeow/JWT/74b4324a2461cbbb7a7661ac602cc57cd8aabe05/JWT-for-JDK6.zip -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 喵大攻城狮 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JWT 2 | ## 项目介绍 3 | ### 预备知识(可能需要科学上网) 4 | + JSON Web Token(JWT)是什么鬼 5 | + 八幅漫画理解使用JSON Web Token设计单点登录系统 6 | 7 | ### 流程图 8 | ![image](https://github.com/bigmeow/JWT/blob/master/WebRoot/flowsheet.JPG) 9 | ### 目录结构 10 | ``` 11 | . 12 | ├── README.md 13 | ├── src 14 | | └── com 15 | | |── filter 16 | | | └── Filter0_CrossOriginResource.java (跨域过滤器) 17 | | | └── Filter1_CheckToken.java (token校验过滤器) 18 | | ├── jwt 19 | | │ └── Jwt.java 20 | | │ └── JwtTestCase.java (测试用例) 21 | | │ └── TokenState.java (token状态枚举) 22 | | | 23 | | └── servlet 24 | | └── AuthorServlet.java 25 | ├── WebRoot 26 | | |── WEB-INFO 27 | | |── index.jsp 28 | | |── login.html 29 | | |── main.html 30 | | └── jquery-2.1.0.js 31 | ``` 32 | ## 由于使用了servlet3.0语法,运行环境要求JDK7以及以上,Tomcat7以及以上( 根目录下附带降级版本,支持jdk1.6,tomcat6 ,暂不可用,有空再更新) 33 | 本项目依赖于下面jar包: 34 | + nimbus-jose-jwt-4.13.1.jar (一款开源的成熟的JSON WEB TOKEN 解决方法,本仓库的代码是对其的进一步封装) 35 | + json-smart-2.0-RC2.jar和asm-1.0-RC1.jar (依赖jar包,主要用于JSONObject序列化) 36 | + cors-filter-2.2.1.jar和java-property-utils-1.9.1.jar(用于处理跨域ajax请求) 37 | + junit.jar(单元测试相关jar包) 38 | 39 | 40 | 核心类Jwt.java结构: 41 | > 2个静态方法createToken和validToken,分别用于生成TOKEN和校验TOKEN; 42 | > 定义了枚举TokenState,用于表示验证token时的结果,用户可根据结果进行不同处理: 43 | * EXPIRED token过期 44 | * INVALID token无效(包括token不合法,token格式不对,校验时异常) 45 | * VALID token有效 46 | 47 | 48 | 49 | ## 使用示例 50 | ### 获取token 51 | 52 | ```Java 53 | Map payload=new HashMap(); 54 | Date date=new Date(); 55 | payload.put("uid", "291969452");//用户id 56 | payload.put("iat", date.getTime());//生成时间 57 | payload.put("ext",date.getTime()+1000*60*60);//过期时间1小时 58 | String token=Jwt.createToken(payload); 59 | System.out.println("token:"+token); 60 | 61 | ``` 62 | 63 | ### 校验token 64 | ```Java 65 | 66 | String token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIyOTE5Njk0NTIiLCJpYXQiOjE0NjA0MzE4ODk2OTgsImV4dCI6MTQ2MDQzNTQ4OTY5OH0.RAa71BnklRMPyPhYBbxsfJdtXBnXeWevxcXLlwC2PrY"; 67 | Map result=Jwt.validToken(token); 68 | 69 | String state=(String)result.get("state"); 70 | switch (TokenState.getTokenState(state)) { 71 | case VALID: 72 | //To do somethings 73 | System.out.println("有效token"); 74 | break; 75 | case EXPIRED: 76 | System.out.println("过期token"); 77 | break; 78 | case INVALID: 79 | System.out.println("无效的token"); 80 | break; 81 | } 82 | 83 | System.out.println("返回结果数据是:" +result.toString()); 84 | 85 | 86 | 87 | ``` 88 | 89 | ## 一些坑 90 | 跨域过滤器一定要比其他过滤器先执行,不然会有些问题:在web.xml文件中,过滤器的执行顺序是按照在web.xml中从上到下书写的顺序来执行的;在servlet3.0注解中,filter执行顺序是按照文件名自然排序来决定执行顺序的,比如名字叫A的filter就比B先执行 91 | -------------------------------------------------------------------------------- /WebRoot/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /WebRoot/WEB-INF/.gitignore: -------------------------------------------------------------------------------- 1 | /classes 2 | -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/asm-1.0-RC1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigmeow/JWT/74b4324a2461cbbb7a7661ac602cc57cd8aabe05/WebRoot/WEB-INF/lib/asm-1.0-RC1.jar -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/cors-filter-2.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigmeow/JWT/74b4324a2461cbbb7a7661ac602cc57cd8aabe05/WebRoot/WEB-INF/lib/cors-filter-2.2.1.jar -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/java-property-utils-1.9.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigmeow/JWT/74b4324a2461cbbb7a7661ac602cc57cd8aabe05/WebRoot/WEB-INF/lib/java-property-utils-1.9.1.jar -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/json-smart-2.0-RC2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigmeow/JWT/74b4324a2461cbbb7a7661ac602cc57cd8aabe05/WebRoot/WEB-INF/lib/json-smart-2.0-RC2.jar -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/nimbus-jose-jwt-4.13.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigmeow/JWT/74b4324a2461cbbb7a7661ac602cc57cd8aabe05/WebRoot/WEB-INF/lib/nimbus-jose-jwt-4.13.1.jar -------------------------------------------------------------------------------- /WebRoot/flowsheet.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bigmeow/JWT/74b4324a2461cbbb7a7661ac602cc57cd8aabe05/WebRoot/flowsheet.JPG -------------------------------------------------------------------------------- /WebRoot/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 | <% 3 | String path = request.getContextPath(); 4 | String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 5 | %> 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /WebRoot/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 登陆 7 | 8 | 22 | 23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 |
31 | 32 |
33 |
34 | 35 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /WebRoot/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 我是主页面 10 |
11 |
12 | 13 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/com/filter/Filter0_CrossOriginResource.java: -------------------------------------------------------------------------------- 1 | package com.filter; 2 | 3 | import java.io.IOException; 4 | import javax.servlet.FilterChain; 5 | import javax.servlet.FilterConfig; 6 | import javax.servlet.ServletException; 7 | import javax.servlet.ServletRequest; 8 | import javax.servlet.ServletResponse; 9 | import javax.servlet.annotation.WebFilter; 10 | import javax.servlet.annotation.WebInitParam; 11 | import com.thetransactioncompany.cors.CORSConfiguration; 12 | import com.thetransactioncompany.cors.CORSFilter; 13 | /** 14 | * 服务端跨域处理过滤器,该过滤器需要依赖cors-filter-2.2.1.jar和java-property-utils-1.9.1.jar 15 | * @author running@vip.163.com 16 | * 17 | */ 18 | @WebFilter(urlPatterns={"/*"},asyncSupported=true, 19 | initParams={ 20 | @WebInitParam(name="cors.allowOrigin",value="*"), 21 | @WebInitParam(name="cors.supportedMethods",value="CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, TRACE"), 22 | @WebInitParam(name="cors.supportedHeaders",value="token,Accept, Origin, X-Requested-With, Content-Type, Last-Modified"),//注意,如果token字段放在请求头传到后端,这里需要配置 23 | @WebInitParam(name="cors.exposedHeaders",value="Set-Cookie"), 24 | @WebInitParam(name="cors.supportsCredentials",value="true") 25 | }) 26 | public class Filter0_CrossOriginResource extends CORSFilter implements javax.servlet.Filter{ 27 | 28 | 29 | public void init(FilterConfig config) throws ServletException { 30 | System.out.println("跨域资源处理过滤器初始化了"); 31 | super.init(config); 32 | } 33 | 34 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 35 | System.out.println("跨域过滤器"); 36 | super.doFilter(request, response, chain); 37 | } 38 | 39 | 40 | public void setConfiguration(CORSConfiguration config) { 41 | super.setConfiguration(config); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/com/filter/Filter1_CheckToken.java: -------------------------------------------------------------------------------- 1 | package com.filter; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintWriter; 5 | import java.util.Map; 6 | 7 | import javax.servlet.Filter; 8 | import javax.servlet.FilterChain; 9 | import javax.servlet.FilterConfig; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import javax.servlet.annotation.WebFilter; 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | 17 | import net.minidev.json.JSONObject; 18 | 19 | import com.jwt.Jwt; 20 | import com.jwt.TokenState; 21 | /** 22 | * toekn校验过滤器,所有的API接口请求都要经过该过滤器(除了登陆接口) 23 | * @author running@vip.163.com 24 | * 25 | */ 26 | @WebFilter(urlPatterns="/servlet/*") 27 | public class Filter1_CheckToken implements Filter { 28 | 29 | 30 | @Override 31 | public void doFilter(ServletRequest argo, ServletResponse arg1, 32 | FilterChain chain ) throws IOException, ServletException { 33 | HttpServletRequest request=(HttpServletRequest) argo; 34 | HttpServletResponse response=(HttpServletResponse) arg1; 35 | // response.setHeader("Access-Control-Allow-Origin", "*"); 36 | if(request.getRequestURI().endsWith("/servlet/login")){ 37 | //登陆接口不校验token,直接放行 38 | chain.doFilter(request, response); 39 | return; 40 | } 41 | //其他API接口一律校验token 42 | System.out.println("开始校验token"); 43 | //从请求头中获取token 44 | String token=request.getHeader("token"); 45 | Map resultMap=Jwt.validToken(token); 46 | TokenState state=TokenState.getTokenState((String)resultMap.get("state")); 47 | switch (state) { 48 | case VALID: 49 | //取出payload中数据,放入到request作用域中 50 | request.setAttribute("data", resultMap.get("data")); 51 | //放行 52 | chain.doFilter(request, response); 53 | break; 54 | case EXPIRED: 55 | case INVALID: 56 | System.out.println("无效token"); 57 | //token过期或者无效,则输出错误信息返回给ajax 58 | JSONObject outputMSg=new JSONObject(); 59 | outputMSg.put("success", false); 60 | outputMSg.put("msg", "您的token不合法或者过期了,请重新登陆"); 61 | output(outputMSg.toJSONString(), response); 62 | break; 63 | } 64 | 65 | 66 | } 67 | 68 | 69 | public void output(String jsonStr,HttpServletResponse response) throws IOException{ 70 | response.setContentType("text/html;charset=UTF-8;"); 71 | PrintWriter out = response.getWriter(); 72 | // out.println(); 73 | out.write(jsonStr); 74 | out.flush(); 75 | out.close(); 76 | 77 | } 78 | 79 | @Override 80 | public void init(FilterConfig arg0) throws ServletException { 81 | System.out.println("token过滤器初始化了"); 82 | } 83 | 84 | @Override 85 | public void destroy() { 86 | 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/com/jwt/Jwt.java: -------------------------------------------------------------------------------- 1 | package com.jwt; 2 | import java.util.Date; 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.nimbusds.jose.JOSEException; 7 | import com.nimbusds.jose.JOSEObjectType; 8 | import com.nimbusds.jose.JWSAlgorithm; 9 | import com.nimbusds.jose.JWSHeader; 10 | import com.nimbusds.jose.JWSObject; 11 | import com.nimbusds.jose.JWSVerifier; 12 | import com.nimbusds.jose.Payload; 13 | import com.nimbusds.jose.crypto.MACSigner; 14 | import com.nimbusds.jose.crypto.MACVerifier; 15 | 16 | import net.minidev.json.JSONObject; 17 | /** 18 | * 19 | * @author running@vip.163.com 20 | * 21 | */ 22 | public class Jwt { 23 | 24 | 25 | /** 26 | * 秘钥 27 | */ 28 | private static final byte[] SECRET="3d990d2276917dfac04467df11fff26d".getBytes(); 29 | 30 | /** 31 | * 初始化head部分的数据为 32 | * { 33 | * "alg":"HS256", 34 | * "type":"JWT" 35 | * } 36 | */ 37 | private static final JWSHeader header=new JWSHeader(JWSAlgorithm.HS256, JOSEObjectType.JWT, null, null, null, null, null, null, null, null, null, null, null); 38 | 39 | /** 40 | * 生成token,该方法只在用户登录成功后调用 41 | * 42 | * @param Map集合,可以存储用户id,token生成时间,token过期时间等自定义字段 43 | * @return token字符串,若失败则返回null 44 | */ 45 | public static String createToken(Map payload) { 46 | String tokenString=null; 47 | // 创建一个 JWS object 48 | JWSObject jwsObject = new JWSObject(header, new Payload(new JSONObject(payload))); 49 | try { 50 | // 将jwsObject 进行HMAC签名 51 | jwsObject.sign(new MACSigner(SECRET)); 52 | tokenString=jwsObject.serialize(); 53 | } catch (JOSEException e) { 54 | System.err.println("签名失败:" + e.getMessage()); 55 | e.printStackTrace(); 56 | } 57 | return tokenString; 58 | } 59 | 60 | 61 | 62 | /** 63 | * 校验token是否合法,返回Map集合,集合中主要包含 state状态码 data鉴权成功后从token中提取的数据 64 | * 该方法在过滤器中调用,每次请求API时都校验 65 | * @param token 66 | * @return Map 67 | */ 68 | public static Map validToken(String token) { 69 | Map resultMap = new HashMap(); 70 | try { 71 | JWSObject jwsObject = JWSObject.parse(token); 72 | Payload payload = jwsObject.getPayload(); 73 | JWSVerifier verifier = new MACVerifier(SECRET); 74 | 75 | if (jwsObject.verify(verifier)) { 76 | JSONObject jsonOBj = payload.toJSONObject(); 77 | // token校验成功(此时没有校验是否过期) 78 | resultMap.put("state", TokenState.VALID.toString()); 79 | // 若payload包含ext字段,则校验是否过期 80 | if (jsonOBj.containsKey("ext")) { 81 | long extTime = Long.valueOf(jsonOBj.get("ext").toString()); 82 | long curTime = new Date().getTime(); 83 | // 过期了 84 | if (curTime > extTime) { 85 | resultMap.clear(); 86 | resultMap.put("state", TokenState.EXPIRED.toString()); 87 | } 88 | } 89 | resultMap.put("data", jsonOBj); 90 | 91 | } else { 92 | // 校验失败 93 | resultMap.put("state", TokenState.INVALID.toString()); 94 | } 95 | 96 | } catch (Exception e) { 97 | //e.printStackTrace(); 98 | // token格式不合法导致的异常 99 | resultMap.clear(); 100 | resultMap.put("state", TokenState.INVALID.toString()); 101 | } 102 | return resultMap; 103 | } 104 | 105 | } 106 | 107 | 108 | -------------------------------------------------------------------------------- /src/com/jwt/JwtTestCase.java: -------------------------------------------------------------------------------- 1 | package com.jwt; 2 | 3 | 4 | import java.util.Date; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import org.junit.Test; 9 | /** 10 | * 单元测试(请自行引入junit4 Jar包) 11 | * @author running@vip.163.com 12 | * 13 | */ 14 | public class JwtTestCase { 15 | @Test 16 | @SuppressWarnings("unchecked") 17 | public void test1() { 18 | // 正常生成token---------------------------------------------------------------------------------------------------- 19 | String token = null; 20 | Map payload = new HashMap(); 21 | Date date = new Date(); 22 | payload.put("uid", "291969452");// 用户id 23 | payload.put("iat", date.getTime());// 生成时间:当前 24 | payload.put("ext", date.getTime() + 2000 * 60 * 60);// 过期时间2小时 25 | token = Jwt.createToken(payload); 26 | System.out.println("新生成的token是:" + token+"\n马上将该token进行校验"); 27 | Map resultMap = Jwt.validToken(token); 28 | System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) ); 29 | HashMap dataobj = (HashMap) resultMap.get("data"); 30 | System.out.println("从token中取出的payload数据是:" +dataobj.toString()); 31 | 32 | } 33 | 34 | public void test2() { 35 | // 校验过期---------------------------------------------------------------------------------------------------- 36 | String token = null; 37 | Map payload = new HashMap(); 38 | Date date = new Date(); 39 | payload.put("uid", "291969452");// 用户id 40 | payload.put("iat", date.getTime());// 生成时间 41 | payload.put("ext", date.getTime());// 过期时间就是当前 42 | token = Jwt.createToken(payload); 43 | System.out.println("新生成的token是:" + token+"\n马上将该token进行校验"); 44 | Map resultMap = Jwt.validToken(token); 45 | System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) ); 46 | 47 | } 48 | 49 | @SuppressWarnings("unchecked") 50 | public void test2_1() { 51 | // 不校验过期(当payload中无过期ext字段时)---------------------------------------------------------------------------------------------------- 52 | String token = null; 53 | Map payload = new HashMap(); 54 | Date date = new Date(); 55 | payload.put("uid", "291969452");// 用户id 56 | payload.put("iat", date.getTime());// 生成时间 57 | token = Jwt.createToken(payload); 58 | System.out.println("新生成的token是:" + token+"\n马上将该token进行校验"); 59 | Map resultMap = Jwt.validToken(token); 60 | System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) ); 61 | HashMap dataobj = (HashMap) resultMap.get("data"); 62 | System.out.println("从token中取出的payload数据是:" +dataobj.toString()); 63 | 64 | } 65 | 66 | public void test3() { 67 | // 校验非法token的情况---------------------------------------------------------------------------------------------------- 68 | String token = null; 69 | Map payload = new HashMap(); 70 | Date date = new Date(); 71 | payload.put("uid", "291969452");// 用户id 72 | payload.put("iat", date.getTime());// 生成时间 73 | payload.put("ext", date.getTime());// 过期时间就是当前 74 | 75 | token = Jwt.createToken(payload); 76 | System.out.println("新生成的token是:" + token); 77 | System.out.println("将新生成的token加点调料再来进行校验"); 78 | token = token + "YouAreSB"; 79 | Map resultMap = Jwt.validToken(token); 80 | System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) ); 81 | System.out.println("原因是(非法token,payload参数可能经过中间人篡改,或者别人伪造的token)" ); 82 | 83 | } 84 | 85 | public void test4() { 86 | // 校验异常的情况---------------------------------------------------------------------------------------------------- 87 | String token = "123"; 88 | System.out.println("我胡乱传一个token:" + token); 89 | Map resultMap = Jwt.validToken(token); 90 | System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) ); 91 | System.out.println("原因是(token格式不合法导致的程序异常)"); 92 | 93 | } 94 | 95 | 96 | public String getResult(String state) { 97 | switch (TokenState.getTokenState(state)) { 98 | case VALID: 99 | //To do somethings 100 | state = "有效token"; 101 | break; 102 | case EXPIRED: 103 | state = "过期token"; 104 | break; 105 | case INVALID: 106 | state = "无效的token"; 107 | break; 108 | } 109 | return state; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/com/jwt/TokenState.java: -------------------------------------------------------------------------------- 1 | package com.jwt; 2 | 3 | /** 4 | * 枚举,定义token的三种状态 5 | * @author running@vip.163.com 6 | * 7 | */ 8 | public enum TokenState { 9 | /** 10 | * 过期 11 | */ 12 | EXPIRED("EXPIRED"), 13 | /** 14 | * 无效(token不合法) 15 | */ 16 | INVALID("INVALID"), 17 | /** 18 | * 有效的 19 | */ 20 | VALID("VALID"); 21 | 22 | private String state; 23 | 24 | private TokenState(String state) { 25 | this.state = state; 26 | } 27 | 28 | /** 29 | * 根据状态字符串获取token状态枚举对象 30 | * @param tokenState 31 | * @return 32 | */ 33 | public static TokenState getTokenState(String tokenState){ 34 | TokenState[] states=TokenState.values(); 35 | TokenState ts=null; 36 | for (TokenState state : states) { 37 | if(state.toString().equals(tokenState)){ 38 | ts=state; 39 | break; 40 | } 41 | } 42 | return ts; 43 | } 44 | public String toString() { 45 | return this.state; 46 | } 47 | public String getState() { 48 | return state; 49 | } 50 | public void setState(String state) { 51 | this.state = state; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/com/servlet/AuthorServlet.java: -------------------------------------------------------------------------------- 1 | package com.servlet; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintWriter; 5 | import java.util.Date; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import javax.servlet.ServletException; 10 | import javax.servlet.annotation.WebServlet; 11 | import javax.servlet.http.Cookie; 12 | import javax.servlet.http.HttpServlet; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | import net.minidev.json.JSONObject; 17 | 18 | import com.jwt.Jwt; 19 | @WebServlet(urlPatterns="/author/token",loadOnStartup=1,description="生成token的方法") 20 | public class AuthorServlet extends HttpServlet { 21 | 22 | private static final long serialVersionUID = -8463692428988705309L; 23 | 24 | 25 | public void doGet(HttpServletRequest request, HttpServletResponse response) 26 | throws ServletException, IOException { 27 | String token=request.getHeader("token"); 28 | System.out.println(token); 29 | Map result=Jwt.validToken(token); 30 | //转JSON并输出 31 | PrintWriter out = response.getWriter(); 32 | out.println(new JSONObject(result).toJSONString()); 33 | out.flush(); 34 | out.close(); 35 | } 36 | 37 | public void doPut(HttpServletRequest request, HttpServletResponse response) 38 | throws ServletException, IOException { 39 | Map payload=new HashMap(); 40 | Date date=new Date(); 41 | payload.put("uid", "291969452");//用户id 42 | payload.put("iat", date.getTime());//生成时间 43 | payload.put("ext",date.getTime()+1000*60*60);//过期时间1小时 44 | String token=null; 45 | token=Jwt.createToken(payload); 46 | 47 | response.setContentType("text/html;charset=UTF-8;"); 48 | Cookie cookie=new Cookie("token", token); 49 | cookie.setMaxAge(3600); 50 | response.addCookie(cookie); 51 | PrintWriter out = response.getWriter(); 52 | out.println(token); 53 | out.flush(); 54 | out.close(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/com/servlet/LoginServlet.java: -------------------------------------------------------------------------------- 1 | package com.servlet; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintWriter; 5 | import java.util.Date; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import javax.servlet.ServletException; 10 | import javax.servlet.annotation.WebServlet; 11 | import javax.servlet.http.HttpServlet; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | import net.minidev.json.JSONObject; 16 | 17 | import com.jwt.Jwt; 18 | @WebServlet(urlPatterns="/servlet/login",loadOnStartup=1) 19 | public class LoginServlet extends HttpServlet { 20 | 21 | private static final long serialVersionUID = 5285600116871825644L; 22 | 23 | /** 24 | * 校验用户名密码 25 | */ 26 | public void doPost(HttpServletRequest request, HttpServletResponse response) 27 | throws ServletException, IOException { 28 | 29 | String userName=request.getParameter("userName"); 30 | String password =request.getParameter("password"); 31 | JSONObject resultJSON=new JSONObject(); 32 | 33 | //用户名密码校验成功后,生成token返回客户端 34 | if("admin".equals(userName)&&"123".equals(password)){ 35 | //生成token 36 | Map payload=new HashMap(); 37 | Date date=new Date(); 38 | payload.put("uid", "admin");//用户ID 39 | payload.put("iat", date.getTime());//生成时间 40 | payload.put("ext",date.getTime()+1000*60*60);//过期时间1小时 41 | String token=Jwt.createToken(payload); 42 | 43 | 44 | resultJSON.put("success", true); 45 | resultJSON.put("msg", "登陆成功"); 46 | resultJSON.put("token", token); 47 | 48 | }else{ 49 | resultJSON.put("success", false); 50 | resultJSON.put("msg", "用户名密码不对"); 51 | } 52 | //输出结果 53 | output(resultJSON.toJSONString(), response); 54 | 55 | 56 | 57 | } 58 | 59 | 60 | 61 | public void output(String jsonStr,HttpServletResponse response) throws IOException{ 62 | response.setContentType("text/html;charset=UTF-8;"); 63 | PrintWriter out = response.getWriter(); 64 | out.println(jsonStr); 65 | out.flush(); 66 | out.close(); 67 | 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/com/servlet/mainServlet.java: -------------------------------------------------------------------------------- 1 | package com.servlet; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintWriter; 5 | import java.util.HashMap; 6 | 7 | import javax.servlet.ServletException; 8 | import javax.servlet.annotation.WebServlet; 9 | import javax.servlet.http.HttpServlet; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | import net.minidev.json.JSONObject; 14 | @WebServlet(urlPatterns="/servlet/getInfo",loadOnStartup=1) 15 | public class mainServlet extends HttpServlet { 16 | 17 | private static final long serialVersionUID = -1643121334640537359L; 18 | 19 | @SuppressWarnings("unchecked") 20 | public void doGet(HttpServletRequest request, HttpServletResponse response) 21 | throws ServletException, IOException { 22 | System.out.println("正在调用获取信息的接口"); 23 | //将过滤器中存入的payload数据取出来 24 | HashMap data=(HashMap) request.getAttribute("data"); 25 | //payload中的数据可以用来做查询,比如我们在登陆成功时将用户ID存到了payload中,我们可以将它取出来,去数据库查询这个用户的所有信息; 26 | //而不是用request.getParameter("uid")方法来获取前端传给我们的uid,因为前端的参数时可篡改的不完全可信的,而我们从payload中取出来的数据是从token中 27 | //解密取出来的,在秘钥没有被破解的情况下,它是绝对可信的;这样可以避免别人用这个接口查询非自己用户ID的相关信息 28 | JSONObject resp=new JSONObject(); 29 | resp.put("success", true); 30 | resp.put("msg", "成功"); 31 | resp.put("data", data); 32 | output(resp.toJSONString(), response); 33 | } 34 | 35 | public void output(String jsonStr,HttpServletResponse response) throws IOException{ 36 | response.setContentType("text/html;charset=UTF-8;"); 37 | PrintWriter out = response.getWriter(); 38 | out.println(jsonStr); 39 | out.flush(); 40 | out.close(); 41 | 42 | } 43 | 44 | } 45 | --------------------------------------------------------------------------------