服务器如何验证jwt,spring集成jwt验证方式,token验证

为何要告别session?有这样一个场景,系统的数据量达到千万级,须要几台服务器部署,当一个用户在其中一台服务器登陆后,用session保存其登陆信息,其余服务器怎么知道该用户登陆了?(单点登陆),固然解决办法有,能够用spring-session。若是该系统同时为移动端服务呢?移动端经过url向后台要数据,若是用session,经过sessionId识别用户,万一sessionId被截获了,别人能够利用sessionId向后台要数据,就有安全隐患了。因此有必要跟session说拜拜了。服务端不须要存储任何用户的信息,用户的验证应该放在客户端,jwt就是这种方式!

什么是jwt?

d15f816ac786f43432615205bd78694b.png

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

1.pom.xml 导入jwt的包web

com.auth0java-jwt2.2.0

1

2

3

4

5

6

7

2.编写jwt的工具类,有加密解密功能就好spring

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<>?N<: private static final string exp="exp" payload="payload" public> String sign(T object, long maxAge) { try { final JWTSigner signer = new JWTSigner(SECRET); final Map claims = new HashMap(); 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 unsign(String jwt, Class classT) { final JWTVerifier verifier = new JWTVerifier(SECRET); try { final Map 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; } } }

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

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

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; }

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

4.在用户登陆时,把loginId和token返回给前台,之后用户每次请求时,都得带上这两个参数,后台拿到token后解密出loginId,与用户传递过来的loginId比较,若是相同,则说明用户身份合法。由于是每一个登陆事后的每一个请求,这里用springmvc的拦截器作json

1

2

3

4

5

6

7

8

9

10

11

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(); } }

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

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

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

1

2

3

4

5

6

7

7.最后分享一个类,用于返回给客户端的万能类,我以为它能够知足通常的接口session

import java.util.HashMap;

import java.util.Map;

public class ResponseData { private final String message; private final int code; private final Map data = new HashMap(); public String getMessage() { return message; } public int getCode() { return code; } public Map 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"); } }

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值