代码地址如下:
http://www.demodashi.com/demo/12531.html

0、准备工作

0-1运行环境

  1. jdk1.8
  2. maven
  3. 一个能支持以上两者的代码编辑器,作者使用的是IDEA。

0-2知识储备

  1. 对SpringBoot框架有所了解
  2. 对token的定义有了解
  3. 本案例简单,代码注释较少,有不明白的地方,或者不正确的地方,欢迎联系作者本人或留言。

1、设计思路

1-1 项目结构

本案例模拟用户登录/注册后,服务器返回一个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

@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<String, Object> 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<String,Object> validateToken(String token) {
Map<String,Object> resp = new HashMap<String,Object>();
if (token != null) {
// 解析token
try {
Map<String, Object> 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

@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

@RestController
public class HelloController {
@RequestMapping("/hello")
public Map login(HttpServletRequest request){
String token = request.getParameter("token");
return JwtUtil.validateToken(token);
}
}

2.4测试

用户登录后,会返回一串token,咱们可以用token进行下一步请求:

当我再次访问登录接口之后,却用旧的token访问测试接口时:

3 总结

上面是贴出的主要代码,完整的请下载demo包,有不明白的地方请在下方评论,或者联系邮箱yaoyunxiaoli@163.com。

我是妖云小离,这是我第二次在Demo大师上发文章,感谢阅读。

基于JWT的Token开发案例

代码地址如下:
http://www.demodashi.com/demo/12531.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

基于JWT的Token开发案例的更多相关文章

  1. ASP.NET WebApi 基于JWT实现Token签名认证

    一.前言 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebServi ...

  2. token 与 基于JWT的Token认证

    支持跨域访问,无状态认证 token特点 支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输 无状态(也称:服务端可扩展行): ...

  3. 基于JWT的Token认证机制及安全问题

    [干货分享]基于JWT的Token认证机制及安全问题 https://bbs.huaweicloud.com/blogs/06607ea7b53211e7b8317ca23e93a891

  4. ASP.NET Web API 2系列(四):基于JWT的token身份认证方案

    1.引言 通过前边的系列教程,我们可以掌握WebAPI的初步运用,但是此时的API接口任何人都可以访问,这显然不是我们想要的,这时就需要控制对它的访问,也就是WebAPI的权限验证.验证方式非常多,本 ...

  5. 基于JWT的Token身份验证

    ​ 身份验证,是指通过一定的手段,完成对用户身份的确认.为了及时的识别发送请求的用户身份,我们调研了常见的几种认证方式,cookie.session和token. 1.Cookie ​ cookie是 ...

  6. 基于JWT实现token验证

    JWT的介绍 Json Web Token(JWT)是目前比较流行的跨域认证解决方案,是一种基于JSON的开发标准,由于数据是可以经过签名加密的,比较安全可靠,一般用于前端和服务器之间传递信息,也可以 ...

  7. iOS 开发之基于JWT的Token认证机制及解析

    在移动端和服务端通信中,一般有两种认证方式:token 和 session. 1.session/cookie 认证机制: 在服务端创建一个Session对象,同时在客户端的浏览器端创建一个Cooki ...

  8. 基于jwt的token验证

    一.什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). 该token被设计为紧凑且安全的,特别适用于分布 ...

  9. 基于JWT的token身份认证方案

    一.使用JSON Web Token的好处? 1.性能问题. JWT方式将用户状态分散到了客户端中,相比于session,可以明显减轻服务端的内存压力. Session方式存储用户id的最大弊病在于S ...

随机推荐

  1. [置顶] Linux 虚拟地址与物理地址的映射关系分析【转】

    转自:http://blog.csdn.net/ordeder/article/details/41630945 版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文 ...

  2. android与java的关系

    摘自:http://bbs.51cto.com/thread-944897-1.html   相信学习android的人都会想过或者想知道这个问题,那就请你耐心的看完这篇文章吧,你会对android与 ...

  3. (3) python--matplotlib

    (一)1.如何绘制散点图 import numpy as np import matplotlib.pyplot as plt # 如何绘制散点图 # 先随机生成数据 x = np.array(ran ...

  4. JUnit--BeforeClass、AfterClass、Before、After示例

    JUnit 4 使用 Java 5 中的注解(annotation),以下是JUnit 4 常用的几个 annotation 介绍@Before:初始化方法@After:释放资源@Test:测试方法, ...

  5. 微信小程序开发,上传wx.uploadFile 返回参数处理

    这真的是个坑,前端看了半天,说是字符串,让后台处理,后台说返回的是正确的,原来这个请求就是返回的string类型,见下图,无法取到code,需要前台自己转化. 以下为百度出来的参考: wx.reque ...

  6. Strobogrammatic Number -- LeetCode

    A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...

  7. Bluetooth篇 开发实例之八 匹配

    自己写的App匹配蓝牙设备,不需要通过系统设置去连接. 匹配和通信是两回事. 用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK ...

  8. ANDROID模拟器访问本地WEB应用10.0.2.2

    在一般的Java Web程序开发中,我们通常使用localhost或者127.0.0.1来访问本机的Web服务,但是如果我们在Android模拟器中也采用同样的地址来访问,Android模拟器将无法正 ...

  9. jtds链接SqlServer数据库(整合)

    先前使用的时候没做汇总,现在结合遇到的问题总结下. 开始使用jdbc驱动配置调用SqlServer不合适,根据网上的资料修改成了jtds配置方式. 当时使用的maven配置,配置如下: <spa ...

  10. 开源 ≠ 免费,开源协议License详解

    凡是做过软件开发的,都会接触到开源软件或开源组件,它们都会基于某种协议来提供源码和授权,那么这些开源协议到底有哪些约束呢? 在介绍之前,必须告诉大家,针对开源协议,必须打消“开源 = 免费”这个念头, ...