├── .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 | 
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 |
--------------------------------------------------------------------------------