你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
首页
热门
推荐
精选
登录
|
注册
基于JWT的Token开发案例
立即下载
用AI写一个
金额:
1
元
支付方式:
友情提醒:源码购买后不支持退换货
立即支付
我要免费下载
发布时间:2018-02-07
292人
|
浏览:14950次
|
收藏
|
分享
技术:SpringBoot,SpringData,JWT
运行环境:jdk1.8.maven
概述
使用JWT来实现Token的生成与验证,用户登录后服务器返回token,此后用户便用token当做通行证与服务器交互。
详细
## 0、准备工作 ### 0-1运行环境 1. jdk1.8 2. maven 3. 一个能支持以上两者的代码编辑器,作者使用的是IDEA。 ### 0-2知识储备 1. 对SpringBoot框架有所了解 2. 对token的定义有了解 3. 本案例简单,代码注释较少,有不明白的地方,或者不正确的地方,欢迎联系作者本人或留言。 ## 1、设计思路 ### 1-1 项目结构 ![项目结构](/contentImages/image/20180206/pL6aVUIfgPXmQsqWDJc.png "项目结构") 本案例模拟用户登录/注册后,服务器返回一个token用于用户后续操作。 /controller/HelloController.java:测试token的接口 /controller/UserController.java:用户注册/登录的接口 /entity/User.java:用户实体类,属性有 用户ID,用户名,密码,邮箱,上次登录时间。 /repository/UserRepository:实现SpringData接口的数据库操作类,可以很方便的进行CRUD等操作。 /Reponse/UserResponse.java:接口返回数据的实体类。 /util/Constants.java:存放常量的工具类。 /util/JwtUtil.java:Jwt工具类,可以生成、解析Jwt。 ### 1-2 实现难点 1. 对Jwt的理解,可以参考http://blog.leapoahead.com/2015/09/06/understanding-jwt/ 2. JwtUtil工具类的开发 ## 2 具体实现 ### 2-1 JwtUtil.java ```java @Component public class JwtUtil { private static UserRepository userRepository; @Autowired public JwtUtil(UserRepository userRepository) { JwtUtil.userRepository = userRepository; } public static final long EXPIRATION_TIME = 3600_000_000L; // 1000 hour static final String SECRET = "ThisIsASecret"; static final String TOKEN_PREFIX = "Bearer"; static final String HEADER_STRING = "Authorization"; public static String generateToken(String username,Date generateTime) { HashMap
map = new HashMap<>(); //可以把任何安全的数据放到map里面 map.put("username", username); map.put("generateTime",generateTime); String jwt = Jwts.builder() .setClaims(map) .setExpiration(new Date(generateTime.getTime() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SECRET) .compact(); return jwt; } /** * @param token * @return */ public static Map
validateToken(String token) { Map
resp = new HashMap
(); if (token != null) { // 解析token try { Map
body = Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token.replace(TOKEN_PREFIX, "")) .getBody(); String username = (String) (body.get("username")); Date generateTime = new Date((Long)body.get("generateTime")); if(username == null || username.isEmpty()){ resp.put("ERR_MSG",Constants.ERR_MSG_USERNAME_EMPTY); return resp; } //账号在别处登录 if(userRepository.findByUsername(username).getLastLoginTime().after(generateTime)){ resp.put("ERR_MSG",Constants.ERR_MSG_LOGIN_DOU); return resp; } resp.put("username",username); resp.put("generateTime",generateTime); return resp; }catch (SignatureException | MalformedJwtException e) { // TODO: handle exception // don't trust the JWT! // jwt 解析错误 resp.put("ERR_MSG",Constants.ERR_MSG_TOKEN_ERR); return resp; } catch (ExpiredJwtException e) { // TODO: handle exception // jwt 已经过期,在设置jwt的时候如果设置了过期时间,这里会自动判断jwt是否已经过期,如果过期则会抛出这个异常,我们可以抓住这个异常并作相关处理。 resp.put("ERR_MSG",Constants.ERR_MSG_TOKEN_EXP); return resp; } }else { resp.put("ERR_MSG",Constants.ERR_MSG_TOKEN_EMPTY); return resp; } } } ``` ### 2.2 UserController.java ```java @RestController @RequestMapping("/user") public class UserController { @Autowired private UserRepository userRepository; //注册或登录 @RequestMapping("/login") @Transactional public UserResponse login(User user){ String username = user.getUsername(); String password = user.getPassword(); //TODO 检验参数的完整性 UserResponse userResponse = new UserResponse(); User tUser = userRepository.findByUsername(username); //检验username是否存在 user.setLastLoginTime(new Date()); if(tUser!=null){ //检验密码是否正确 if(!tUser.getPassword().equals(password)) { userResponse.setErrorNum(Constants.ERR_NUM_PWD_ERR); userResponse.setErrorMsg(Constants.ERR_MSG_PWD_ERR); return userResponse; } userRepository.updateLastLoginTimeByUserName(user.getLastLoginTime(),username); }else { try { tUser = userRepository.save(user); } catch (Exception e) { userResponse.setErrorNum(Constants.ERR_NUM_SERVER_ERR); userResponse.setErrorMsg(Constants.ERR_MSG_SERVER_ERR); return userResponse; } } userResponse.setErrorNum(Constants.ERR_NUM_OK); userResponse.setErrorMsg(Constants.ERR_MSG_OK); userResponse.setUserName(username); userResponse.setUserId(tUser.getId()); userResponse.setToken(JwtUtil.generateToken(username,user.getLastLoginTime())); return userResponse; } } ``` ### 2.3 HelloController.java ```java @RestController public class HelloController { @RequestMapping("/hello") public Map login(HttpServletRequest request){ String token = request.getParameter("token"); return JwtUtil.validateToken(token); } } ``` ### 2.4测试 ![登录](/contentImages/image/20180206/QshyFvIZpUOud1wYqCj.png "登录") 用户登录后,会返回一串token,咱们可以用token进行下一步请求: ![测试token](/contentImages/image/20180206/0SNXYM9DvnimaqLS1B3.png "测试token") 当我再次访问登录接口之后,却用旧的token访问测试接口时: ![别处登录](/contentImages/image/20180206/R6UzYWr5hIDCMky2J39.png "别处登录") ## 3 总结 上面是贴出的主要代码,完整的请下载demo包,有不明白的地方请在下方评论,或者联系邮箱yaoyunxiaoli@163.com。 我是妖云小离,这是我第二次在Demo大师上发文章,感谢阅读。
本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
感谢
19
手机上随时阅读、收藏该文章 ?请扫下方二维码
相似例子推荐
评论
作者
妖云小离
购买服务
购买服务
服务描述:
技术解答,demo运行
服务价格:
¥15
我要联系
5
例子数量
376
帮助
26
感谢
评分详细
可运行:
4.5
分
代码质量:
4.5
分
文章描述详细:
4.5
分
代码注释:
4.5
分
综合:
4.5
分
作者例子
Redis互斥锁?没那么简单!
基于JWT的Token开发案例
基于SpringMVC+Ext.js的权限管理系统(无权限框架)
基于SpringBoot可配置的图片服务器
基于阿里egg框架搭建博客