java http json token_Json web token 详解

下面我们用springmvc和jwt的类库来实现一个例子。

要使用jwt,需要pom.xml中添加如下依赖

com.auth0

java-jwt

3.2.0

下面贴一个完整的pom.xml

4.0.0

org.jstudioframework

jstudio-jwt

1.0-SNAPSHOT

UTF-8

4.12

4.3.7.RELEASE

2.8.4

3.2.0

1.2

2.5

2.2

junit

junit

${junit.version}

test

com.auth0

java-jwt

${java.jwt.version}

com.fasterxml.jackson.core

jackson-databind

${jackson.version}

com.fasterxml.jackson.core

jackson-core

${jackson.version}

org.springframework

spring-core

${spring.version}

org.springframework

spring-beans

${spring.version}

org.springframework

spring-context

${spring.version}

org.springframework

spring-context-support

${spring.version}

org.springframework

spring-web

${spring.version}

org.springframework

spring-webmvc

${spring.version}

javax.servlet

jstl

${jstl.version}

javax.servlet

servlet-api

${servlet-api.version}

provided

javax.servlet.jsp

jsp-api

${jsp-api.version}

provided

org.apache.tomcat.maven

tomcat7-maven-plugin

8080

/

http://127.0.0.1:8080/manager/text

tomcat

tomcat

一。定义一个jwt的工具类,具有加密和解密token的功能

importjava.util.HashMap;importjava.util.Map;/*** JwtToken*/

public classJwtToken {//密钥

private static final String SECRET = "secret";//jackson

private static ObjectMapper mapper = newObjectMapper();/*** header数据

*@return

*/

private static MapcreateHead() {

Map map = new HashMap();

map.put("typ", "JWT");

map.put("alg", "HS256");returnmap;

}/*** 生成token

*

*@paramobj 对象数据

*@parammaxAge 有效期

*@param

*@return

*/

public static String sign(T obj, long maxAge) throwsUnsupportedEncodingException, JsonProcessingException {

JWTCreator.Builder builder=JWT.create();

builder.withHeader(createHead())//header

.withSubject(mapper.writeValueAsString(obj)); //payload

if (maxAge >= 0) {long expMillis = System.currentTimeMillis() +maxAge;

Date exp= newDate(expMillis);

builder.withExpiresAt(exp);

}returnbuilder.sign(Algorithm.HMAC256(SECRET));

}/*** 解密

*@paramtoken token字符串

*@paramclassT 解密后的类型

*@param

*@return

*/

public static T unsign(String token, Class classT) throwsIOException {

JWTVerifier verifier=JWT.require(Algorithm.HMAC256(SECRET)).build();

DecodedJWT jwt=verifier.verify(token);

Date exp=jwt.getExpiresAt();if(exp!=null&&exp.after(newDate())){

String subject=jwt.getSubject();returnmapper.readValue(subject, classT);

}return null;

}

}

二。 登录时根据用户传来的username和password验证身份,如果合法,便给该用户jwt加密生成token

packagejwt.controller;importcom.fasterxml.jackson.core.JsonProcessingException;importjwt.JwtToken;importjwt.model.User;importjwt.util.ResponseEntity;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.ResponseBody;importjavax.servlet.http.HttpServletRequest;importjava.io.UnsupportedEncodingException;/*** 用户登录*/@Controllerpublic classLoginController {

@RequestMapping(value="login", produces = "application/json; charset=utf-8")

@ResponseBodypublic ResponseEntity login(HttpServletRequest request, @RequestParam( "username") String username,

@RequestParam("password") String password) throwsUnsupportedEncodingException, JsonProcessingException {

ResponseEntity responseEntity=ResponseEntity.ok();if("admin".equals(username) && "admin".equals(password)) {//模拟用户数据,真实环境需要到数据库验证

User user = newUser();

user.setId(123456);

user.setUsername(username);//给用户jwt加密生成token

String token = JwtToken.sign(user, 60L * 1000L * 30L);//封装成对象返回给客户端

responseEntity.putDataValue("userId", user.getId());

responseEntity.putDataValue("token", token);

responseEntity.putDataValue("user", user);

}else{

responseEntity=ResponseEntity.customerError();

}returnresponseEntity;

}

}

User用户类如下

packagejwt.model;/*** User bean*/

public classUser {private longid;privateString username;privateString password;public longgetId() {returnid;

}public void setId(longid) {this.id =id;

}publicString getUsername() {returnusername;

}public voidsetUsername(String username) {this.username =username;

}publicString getPassword() {returnpassword;

}public voidsetPassword(String password) {this.password =password;

}

}

返回给用户端的一个工具类

packagejwt.util;importjava.util.HashMap;importjava.util.Map;public classResponseEntity {public static final String ERRORS_KEY = "errors";private finalString message;private final intcode;private final Map data = newHashMap();publicString getMessage() {returnmessage;

}public intgetCode() {returncode;

}public MapgetData() {returndata;

}publicResponseEntity putDataValue(String key, Object value) {

data.put(key, value);return this;

}private ResponseEntity(intcode, String message) {this.code =code;this.message =message;

}public staticResponseEntity ok() {return new ResponseEntity(200, "Ok");

}public staticResponseEntity notFound() {return new ResponseEntity(404, "Not Found");

}public staticResponseEntity badRequest() {return new ResponseEntity(400, "Bad Request");

}public staticResponseEntity forbidden() {return new ResponseEntity(403, "Forbidden");

}public staticResponseEntity unauthorized() {return new ResponseEntity(401, "unauthorized");

}public staticResponseEntity serverInternalError() {return new ResponseEntity(500, "Server Internal Error");

}public staticResponseEntity customerError() {return new ResponseEntity(1001, "Customer Error");

}

}

三。在用户登录后获得userId和token,以后用户每次请求时,都得带上这两个参数,后台拿到token后解密出userId,与用户传递过来的userId比较,如果相同,则说明用户身份合法。这里用springmvc的拦截器实现验证。

注意:测试使用Params传递参数的,建议正式环境在header里添加参数

packagejwt.interceptor;importcom.fasterxml.jackson.databind.ObjectMapper;importjwt.JwtToken;importjwt.model.User;importjwt.util.ResponseEntity;importorg.springframework.web.servlet.HandlerInterceptor;importorg.springframework.web.servlet.ModelAndView;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.PrintWriter;/*** Token验证拦截器*/

public class UserTokenInterceptor implementsHandlerInterceptor {public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throwsException {

String token= request.getParameter("token");

ResponseEntity responseData=ResponseEntity.ok();//token不存在

if (token != null) {

User user= JwtToken.unsign(token, User.class);

String userId= request.getParameter("userId");//解密token后的userId与用户传来的userId不一致,大多是因为token过期

if (user != null && userId != null && Integer.parseInt(userId) ==user.getId()) {return true;

}

}

responseData=ResponseEntity.forbidden();

response.setContentType("application/json; charset=utf-8");

ObjectMapper mapper= newObjectMapper();

String json=mapper.writeValueAsString(responseData);

PrintWriter out=response.getWriter();

out.print(json);

out.flush();

out.close();return false;

}public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throwsException {

}public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throwsException {

}

}

四。springmvc的配置

http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

五。 使用Chrome插件Postman进行简单的测试

1.登录,http://localhost:8080/login

记下 token和userId

4618f14f12026540dd453f45e9195604.png

2. 测试token鉴权  http://localhost:8080/info

输入正确的userId和token

注意:测试使用Params传递参数的,建议正式环境在header里添加参数

b7b6e95327e028fb411b65c35435a89f.png

输入错误的userId或token,在拦截器那里就被拦截了

f258a369a4362f59c6293fa566048d50.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值