在spring boot專案中加入 JWT
阿新 • • 發佈:2019-01-03
將JWT放到專案中作為一個引數被掉用發起者傳過來作為介面呼叫的口令
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
編寫Jwt服務:
package com. shengqian.demo.service;
public interface JwtService {
String getJwtsString(String ip);
}
package com.shengqian.demo.service.impl;
import com.shengqian.demo.JwtUserName;
import com.shengqian.demo.Util.JwtUser;
import com.shengqian.demo.Util.JwtUtil;
import com.shengqian.demo.service.JwtService;
import org.springframework.stereotype.Service;
import java.sql.Timestamp;
/**
* ClassName JwtServiceImpl
* Description TODO
* Auther chaoj
* Date 2018/12/17 16:18
* Version 1.0
**/
@Service
public class JwtServiceImpl implements JwtService {
@Override
public String getJwtsString(String ip) {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
JwtUser user = new JwtUser.Builder(JwtUserName.ADMIN.getUsername(), timestamp)
.ip(ip)
.password(JwtUserName.ADMIN.getInfo()).build();
long ttlMillis = 30*60;
String jwt = JwtUtil.createJwt(ttlMillis, user);
return jwt;
}
}
再貼上JwtUser和JwtUtil的程式碼,分別是介面呼叫的使用者和Jwt生成的工具類
package com.shengqian.demo.Util;
import java.sql.Timestamp;
/**
* ClassName JwtUser
* Description TODO
* Auther chaoj
* Date 2018/12/17 10:30
* Version 1.0
**/
public class JwtUser {
private final String ip ;
private final String username ;
private final String password ;
private final Timestamp timestamp;
public static class Builder{
private String ip = "0.0.0.0";
private String username;
private String password = "";
private Timestamp timestamp ;
public Builder(String username, Timestamp timestamp){
this.username = username;
this.timestamp = timestamp;
}
public Builder ip(String val){
ip = val;
return this;
}
public Builder password(String val){
password = val;
return this;
}
public JwtUser build(){return new JwtUser(this);}
}
public JwtUser(Builder builder){
ip = builder.ip;
username = builder.username;
password = builder.password;
timestamp = builder.timestamp;
}
public String getPassword() {
return password;
}
public Timestamp getTimestamp() {
return timestamp;
}
public String getIp() {
return ip;
}
public String getUsername() {
return username;
}
}
//JwtUser 的構造器採用Builder模式,這樣可以有效檢查引數,同時也是《Effective Java》推薦的寫法
package com.shengqian.demo.Util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* ClassName JwtUtil
* Description TODO
* Auther chaoj
* Date 2018/12/17 10:49
* Version 1.0
**/
public class JwtUtil {
public static String createJwt(long ttlMillis, JwtUser user){
/**
* @description TODO 建立jwt
* @author chaoj
* @date 2018/12/17 11:03
* @Param [ttlMillis, user]
* @return java.lang.String
* @version 1.0
**/
SignatureAlgorithm algorithm = SignatureAlgorithm.HS256;
long millis = System.currentTimeMillis();
Date date = new Date(millis);
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("ip", user.getIp());
claims.put("username", user.getUsername());
claims.put("timestamp", user.getTimestamp());
String key = user.getPassword();
String subject = user.getUsername();
JwtBuilder jwtBuilder = Jwts.builder().signWith(algorithm, key)
.setClaims(claims)
.setId(UUID.randomUUID().toString())
.setIssuedAt(date)
.setSubject(subject);
if (ttlMillis > 0){
long millisExp = millis + ttlMillis;
Date expdete = new Date(millisExp);
jwtBuilder.setExpiration(expdete);
}
return jwtBuilder.compact();
}
public static Claims parseJwt(String token, JwtUser user){
/**
* @description TODO 解析
* @author chaoj
* @date 2018/12/17 11:07
* @Param [token, user]
* @return io.jsonwebtoken.Claims
* @version 1.0
**/
String key = user.getPassword();
Claims claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token).getBody();
return claims;
}
public static Boolean isVerify(String token, JwtUser user){
String key = user.getPassword();
Claims claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token).getBody();
if (claims.get("password").equals(user.getPassword())){
return true;
}
return false;
}
}
然後寫控制器方法
@RequestMapping(value = Path.LOGIN, method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> userLogin(@RequestParam("phone") final String phone,
@RequestParam("password") final String password,
@RequestParam("ip") final String ip){
Map<String, Object> ans = new HashMap<>();
UserInfoDto dto = userInfoService.getUser(phone);
if (!dto.isRegister()){
dto.setPassword(password);
UserInfoDto dto1 = userInfoService.checkPassword(dto);
if (dto1.isVoladate()){
ans.put("code", 200);
ans.put("info", "成功");
ans.put("key", jwtService.getJwtsString(ip));
return ans;
}
}
ans.put("code", 400);
ans.put("info", "使用者名稱或密碼錯誤");
return ans;
}
如果登入成功,返回一個key,作為介面呼叫的令牌。在我的設計中,jwt將被存放在分散式快取和本地LRU快取中,每次請求過來,先判斷當前伺服器快取中是否有這個key,如果沒有,就去問redis就行了。下一部分我將做把redis整合到spring boot中。
返回demo
{
"code": 200,
"key": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJjaGFvamlsYWppIiwiaXAiOiI2MS4xODYuMTg1LjE4MCIsImV4cCI6MTU0NTAzNjQyOCwiaWF0IjoxNTQ1MDM2NDI2LCJqdGkiOiIxNTUzY2JmMC1jMDBiLTQxZmQtOTdiYy1jM2Q3ZTBhMDM2ZDQiLCJ1c2VybmFtZSI6ImNoYW9qaWxhamkiLCJ0aW1lc3RhbXAiOjE1NDUwMzY0MjY5MTd9.w-XmT9yy7JVVJQt6wIJLjcpVfhN0EVZvc-MpMLVwN58",
"info": "成功"
}