jwt 例子 java_基于JWT的Token开发案例

0、准备工作

0-1运行环境

jdk1.8

maven

一个能支持以上两者的代码编辑器,作者使用的是IDEA。

0-2知识储备

对SpringBoot框架有所了解

对token的定义有了解

本案例简单,代码注释较少,有不明白的地方,或者不正确的地方,欢迎联系作者本人或留言。

1、设计思路

1-1 项目结构

ed44324ef48d07611a9898c039dbe65f.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 实现难点

对Jwt的理解,可以参考http://blog.leapoahead.com/2015/09/06/understanding-jwt/

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

@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测试

1e228ff33e3809d3961728be503003c3.png

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

67ae3eebec42299808cfdca78d8dcf71.png

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

b5ea03d2df187495f82c6a27eab0d08d.png

3 总结

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

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

基于JWT的Token开发案例

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值