JWT(java web token)

忘记在哪里看得了,上传一下简单的jwt示例。

工程目录如下(有两个前端测试页面没截下来,后面有代码):

JWT(java web token)_第1张图片

2.个各类里面的内容

Filter0_CrossOriginResource.java  和  Filter1_CheckToken.java

package com.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

import com.thetransactioncompany.cors.CORSConfiguration;
import com.thetransactioncompany.cors.CORSFilter;
/**
 * 服务端跨域处理过滤器,该过滤器需要依赖cors-filter-2.2.1.jar和java-property-utils-1.9.1.jar
 * 
 *
 */
@WebFilter(urlPatterns={"/*"},asyncSupported=true,
initParams={
	@WebInitParam(name="cors.allowOrigin",value="http://localhost:8080"),	//可以设置确定的域    也可以直接用*,表示所有域都可以访问
	@WebInitParam(name="cors.supportedMethods",value="CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, TRACE"),
	@WebInitParam(name="cors.supportedHeaders",value="token,Accept, Origin, X-Requested-With, Content-Type, Last-Modified"),//注意,如果token字段放在请求头传到后端,这里需要配置
	@WebInitParam(name="cors.exposedHeaders",value="Set-Cookie"),
	@WebInitParam(name="cors.supportsCredentials",value="true")
})
public class Filter0_CrossOriginResource extends CORSFilter implements javax.servlet.Filter{


	public void init(FilterConfig config) throws ServletException {
		System.out.println("跨域资源处理过滤器初始化了,ceshi");
		super.init(config);
	}
	
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("跨域过滤器");
		super.doFilter(request, response, chain);
	}


	public void setConfiguration(CORSConfiguration config) {
		super.setConfiguration(config);
	}
	
}
package com.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.minidev.json.JSONObject;

import com.jwt.Jwt;
import com.jwt.TokenState;
/**
 * toekn校验过滤器,所有的API接口请求都要经过该过滤器(除了登陆接口)
 *
 *
 */
@WebFilter(urlPatterns="/servlet/*")
public class Filter1_CheckToken  implements Filter {


	@Override
	public void doFilter(ServletRequest argo, ServletResponse arg1,
			FilterChain chain ) throws IOException, ServletException {
		HttpServletRequest request=(HttpServletRequest) argo;
		HttpServletResponse response=(HttpServletResponse) arg1;
//		response.setHeader("Access-Control-Allow-Origin", "*");
		if(request.getRequestURI().endsWith("/servlet/login")){
			//登陆接口不校验token,直接放行
			chain.doFilter(request, response);
			return;
		}
		//其他API接口一律校验token
		System.out.println("开始校验token");
		//从请求头中获取token
		String token=request.getHeader("token");
		Map resultMap=Jwt.validToken(token);
		TokenState state=TokenState.getTokenState((String)resultMap.get("state"));
		switch (state) {
		case VALID:
			//取出payload中数据,放入到request作用域中
			request.setAttribute("data", resultMap.get("data"));
			//放行
			chain.doFilter(request, response);
			break;
		case EXPIRED:
		case INVALID:
			System.out.println("无效token");
			//token过期或者无效,则输出错误信息返回给ajax
			JSONObject outputMSg=new JSONObject();
			outputMSg.put("success", false);
			outputMSg.put("msg", "您的token不合法或者过期了,请重新登陆");
			output(outputMSg.toJSONString(), response);
			break;
		}
		
		
	}
	
	
	public void output(String jsonStr,HttpServletResponse response) throws IOException{
		response.setContentType("text/html;charset=UTF-8;");
		PrintWriter out = response.getWriter();
//		out.println();
		out.write(jsonStr);
		out.flush();
		out.close();
		
	}
	
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("token过滤器初始化了");
	}

	@Override
	public void destroy() {
		
	}

}
Jwt.java.java 和  JwtTestCase.java  和  TokenState.java

package com.jwt;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import net.minidev.json.JSONObject;

public class Jwt {
	
    
    /**
     * 秘钥
     */
    private static final byte[] SECRET="3d990d2276917dfac04467df11fff26d".getBytes();
    
    /**
     * 初始化head部分的数据为
     * {
     * 		"alg":"HS256",
     * 		"type":"JWT"
     * }
     */
    private static final JWSHeader HEADER=new JWSHeader(JWSAlgorithm.HS256, JOSEObjectType.JWT, null, null, null, null, null, null, null, null, null, null, null);
    
	/**
	 * 生成token,该方法只在用户登录成功后调用
	 * 
	 * @param Map集合,可以存储用户id,token生成时间,token过期时间等自定义字段
	 * @return token字符串,若失败则返回null
	 */
	public static String createToken(Map payload) {
		String tokenString=null;
		// 创建一个 JWS object
		JWSObject jwsObject = new JWSObject(HEADER, new Payload(new JSONObject(payload)));
		try {
			// 将jwsObject 进行HMAC签名,相当于加密
			jwsObject.sign(new MACSigner(SECRET));
			tokenString=jwsObject.serialize();
		} catch (JOSEException e) {
			System.err.println("签名失败:" + e.getMessage());
			e.printStackTrace();
		}
		return tokenString;
	}
    
    
    
    /**
     * 校验token是否合法,返回Map集合,集合中主要包含    state状态码   data鉴权成功后从token中提取的数据
     * 该方法在过滤器中调用,每次请求API时都校验
     * @param token
     * @return  Map
     */
	public static Map validToken(String token) {
		Map resultMap = new HashMap();
		try {
			JWSObject jwsObject = JWSObject.parse(token);
			Payload payload = jwsObject.getPayload();
			JWSVerifier verifier = new MACVerifier(SECRET);

			if (jwsObject.verify(verifier)) {
				JSONObject jsonOBj = payload.toJSONObject();
				// token校验成功(此时没有校验是否过期)
				resultMap.put("state", TokenState.VALID.toString());
				// 若payload包含ext字段,则校验是否过期
				if (jsonOBj.containsKey("ext")) {
					long extTime = Long.valueOf(jsonOBj.get("ext").toString());
					long curTime = new Date().getTime();
					// 过期了
					if (curTime > extTime) {
						resultMap.clear();
						resultMap.put("state", TokenState.EXPIRED.toString());
					}
				}
				resultMap.put("data", jsonOBj);

			} else {
				// 校验失败
				resultMap.put("state", TokenState.INVALID.toString());
			}

		} catch (Exception e) {
			//e.printStackTrace();
			// token格式不合法导致的异常
			resultMap.clear();
			resultMap.put("state", TokenState.INVALID.toString());
		}
		return resultMap;
	}	
    
}


package com.jwt;


import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
/**
 * 单元测试(请自行引入junit4  Jar包)
 *
 *
 */
public class JwtTestCase {
	@Test
	@SuppressWarnings("unchecked")
	public void test1() {
		// 正常生成token----------------------------------------------------------------------------------------------------
		String token = null;
		Map payload = new HashMap();
		Date date = new Date();
		payload.put("uid", "291969452");// 用户id
		payload.put("iat", date.getTime());// 生成时间:当前
		payload.put("ext", date.getTime() + 2000 * 60 * 60);// 过期时间2小时
		token = Jwt.createToken(payload);
		System.out.println("新生成的token是:" + token+"\n马上将该token进行校验");
		Map resultMap = Jwt.validToken(token);
		System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) );
		HashMap dataobj =  (HashMap) resultMap.get("data");
		System.out.println("从token中取出的payload数据是:" +dataobj.toString());

	}

	public void test2() {
		// 校验过期----------------------------------------------------------------------------------------------------
		String token = null;
		Map payload = new HashMap();
		Date date = new Date();
		payload.put("uid", "291969452");// 用户id
		payload.put("iat", date.getTime());// 生成时间
		payload.put("ext", date.getTime());// 过期时间就是当前
		token = Jwt.createToken(payload);
		System.out.println("新生成的token是:" + token+"\n马上将该token进行校验");
		Map resultMap = Jwt.validToken(token);
		System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) );

	}
	
	@SuppressWarnings("unchecked")
	public void test2_1() {
		// 不校验过期(当payload中无过期ext字段时)----------------------------------------------------------------------------------------------------
		String token = null;
		Map payload = new HashMap();
		Date date = new Date();
		payload.put("uid", "291969452");// 用户id
		payload.put("iat", date.getTime());// 生成时间
		token = Jwt.createToken(payload);
		System.out.println("新生成的token是:" + token+"\n马上将该token进行校验");
		Map resultMap = Jwt.validToken(token);
		System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) );
		HashMap dataobj =  (HashMap) resultMap.get("data");
		System.out.println("从token中取出的payload数据是:" +dataobj.toString());

	}
	
	public void test3() {
		// 校验非法token的情况----------------------------------------------------------------------------------------------------
		String token = null;
		Map payload = new HashMap();
		Date date = new Date();
		payload.put("uid", "291969452");// 用户id
		payload.put("iat", date.getTime());// 生成时间
		payload.put("ext", date.getTime());// 过期时间就是当前
		
		token = Jwt.createToken(payload);
		System.out.println("新生成的token是:" + token);
		System.out.println("将新生成的token加点调料再来进行校验");
		token = token + "YouAreSB";
		Map resultMap = Jwt.validToken(token);
		System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) );
		System.out.println("原因是(非法token,payload参数可能经过中间人篡改,或者别人伪造的token)" );

	}
	
	public void test4() {
		// 校验异常的情况----------------------------------------------------------------------------------------------------
		String token = "123";
		System.out.println("我胡乱传一个token:" + token);
		Map resultMap = Jwt.validToken(token);
		System.out.println("校验结果是:" + getResult((String)resultMap.get("state")) );
		System.out.println("原因是(token格式不合法导致的程序异常)");

	}
	
	
	public String getResult(String state) {
		switch (TokenState.getTokenState(state)) {
		case VALID:
			//To do somethings
			state = "有效token";
			break;
		case EXPIRED:
			state = "过期token";
			break;
		case INVALID:
			state = "无效的token";
			break;
		}
		return state;
	}

}
package com.jwt;

/**
 * 枚举,定义token的三种状态
 *
 *
 */
 public enum TokenState {  
	 /**
	  * 过期
	  */
	EXPIRED("EXPIRED"),
	/**
	 * 无效(token不合法)
	 */
	INVALID("INVALID"), 
	/**
	 * 有效的
	 */
	VALID("VALID");  
	
    private String  state;  
      
    private TokenState(String state) {  
        this.state = state;  
    }
    
    /**
     * 根据状态字符串获取token状态枚举对象
     * @param tokenState
     * @return
     */
    public static TokenState getTokenState(String tokenState){
    	TokenState[] states=TokenState.values();
    	TokenState ts=null;
    	for (TokenState state : states) {
			if(state.toString().equals(tokenState)){
				ts=state;
				break;
			}
		}
    	return ts;
    }
    public String toString() {
    	return this.state;
    }
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
    
}  

AuthorServlet.java  和  LoginServlet.java  和  mainServlet.java

package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.minidev.json.JSONObject;

import com.jwt.Jwt;
@WebServlet(urlPatterns="/author/token",loadOnStartup=1,description="生成token的方法")
public class AuthorServlet extends HttpServlet {

	private static final long serialVersionUID = -8463692428988705309L;
	
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
			String token=request.getHeader("token");
			System.out.println(token);
			Map result=Jwt.validToken(token);
			//转JSON并输出
			PrintWriter out = response.getWriter();
			out.println(new JSONObject(result).toJSONString());
			out.flush();
			out.close();
	}
	
	public void doPut(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Map payload=new HashMap();
		Date date=new Date();
		payload.put("uid", "291969452");//用户id
		payload.put("iat", date.getTime());//生成时间
		payload.put("ext",date.getTime()+1000*60*60);//过期时间1小时
		String token=null;
		token=Jwt.createToken(payload);
		
		response.setContentType("text/html;charset=UTF-8;");
		Cookie cookie=new Cookie("token", token);
		cookie.setMaxAge(3600); 
		response.addCookie(cookie);
		PrintWriter out = response.getWriter();
		out.println(token);
		out.flush();
		out.close();
	}

}

package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.minidev.json.JSONObject;

import com.jwt.Jwt;
@WebServlet(urlPatterns="/servlet/login",loadOnStartup=1)
public class LoginServlet extends HttpServlet {

	private static final long serialVersionUID = 5285600116871825644L;
	
	/**
	 * 校验用户名密码
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String userName=request.getParameter("userName");
		String password =request.getParameter("password");
		JSONObject resultJSON=new JSONObject();
		
		//用户名密码校验成功后,生成token返回客户端
		if("admin".equals(userName)&&"123".equals(password)){
			//生成token
			Map payload=new HashMap();
			Date date=new Date();
			payload.put("uid", "admin");//用户ID
			payload.put("iat", date.getTime());//生成时间
			payload.put("ext",date.getTime()+1000*60*60);//过期时间1小时
			String token=Jwt.createToken(payload);
			

			resultJSON.put("success", true);
			resultJSON.put("msg", "登陆成功");
			resultJSON.put("token", token);
			
		}else{
			resultJSON.put("success", false);
			resultJSON.put("msg", "用户名密码不对");
		}
		//输出结果
		output(resultJSON.toJSONString(), response);
	
		
		
	}
	
	
	
	public void output(String jsonStr,HttpServletResponse response) throws IOException{
		response.setContentType("text/html;charset=UTF-8;");
		PrintWriter out = response.getWriter();
		out.println(jsonStr);
		out.flush();
		out.close();
		
	}

}
package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.minidev.json.JSONObject;
@WebServlet(urlPatterns="/servlet/getInfo",loadOnStartup=1)
public class mainServlet extends HttpServlet {

	private static final long serialVersionUID = -1643121334640537359L;

	@SuppressWarnings("unchecked")
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("正在调用获取信息的接口");
		//将过滤器中存入的payload数据取出来
		HashMap data=(HashMap) request.getAttribute("data");
		//payload中的数据可以用来做查询,比如我们在登陆成功时将用户ID存到了payload中,我们可以将它取出来,去数据库查询这个用户的所有信息;
		//而不是用request.getParameter("uid")方法来获取前端传给我们的uid,因为前端的参数时可篡改的不完全可信的,而我们从payload中取出来的数据是从token中
		//解密取出来的,在秘钥没有被破解的情况下,它是绝对可信的;这样可以避免别人用这个接口查询非自己用户ID的相关信息
		JSONObject resp=new JSONObject();
		resp.put("success", true);
		resp.put("msg", "成功");
		resp.put("data", data);
		output(resp.toJSONString(), response);
	}
	
	public void output(String jsonStr,HttpServletResponse response) throws IOException{
		response.setContentType("text/html;charset=UTF-8;");
		PrintWriter out = response.getWriter();
		out.println(jsonStr);
		out.flush();
		out.close();
	}
	
}

3.前端页面

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>



	
		
		
		
	
	
		
		
		



login.html



	
		
		
		登陆
	
	
	
		


main.html



	
		
		
		
	
	
		我是主页面
		



说明:1.web.xml中什么都不需要写。

         2.前端页面别忘了添加  jquery.min.js

 2.只需要将上面的类按照工程目录复制下来就可以运行了。





你可能感兴趣的:(java,web基础)