1. 導包
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2. 工具類
package com.springCloud.common.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
@ConfigurationProperties(prefix = "jwt.config")
@Component
@Data
public class JWT {
private String key;
private long expiration;
/**
* 創建 JWT
* @param id 用戶的 id 號
* @param subject 用戶名
* @param role 用戶的角色
* @return JWT 編碼.
*/
public String createJWT(String id, String subject, String role) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder jwtBuilder = Jwts.builder()
.setId(id)
.setSubject(subject)
.setIssuedAt(now)
.signWith(SignatureAlgorithm.HS256, key)
.claim("role", role);
if (expiration > 0) {
jwtBuilder.setExpiration(new Date(nowMillis + expiration));
}
return jwtBuilder.compact();
}
/**
* 解析 JWT
* @param jwtString JWT 編碼字符串
* @return String
*/
public Claims parseJWT(String jwtString) {
return Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwtString)
.getBody();
}
}
3. 攔截器
package com.springCloud.user.interceptor;
import com.springCloud.common.util.JWT;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class JwtInterceptor implements HandlerInterceptor {
private JWT jwt;
@Autowired
private JwtInterceptor(JWT jwt) {
this.jwt = jwt;
}
/**
* 如論如何都需要放行, 而攔截需要在操作中去判斷.
* login 中 攔截器只需要將請求頭中包括 token 的令牌進行解析.
*
* @param request 請求
* @param response 響應
* @param handler 處理
* @return boolean
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 得到請求頭中的 Authorization.
String header = request.getHeader("Authorization");
// 判斷是否進行攔截
if (header != null && !"".equals(header) && header.startsWith("Bearer ")) {
// 得到 token
String token = header.substring(7);
// 進行對 token 解析.
try {
Claims claims = jwt.parseJWT(token);
// 得到登錄的角色
String role = (String) claims.get("role");
if ("admin".equals(role)) {
request.setAttribute("token_admin", token);
request.setAttribute("claims_admin", claims);
}
if ("user".equals(role)) {
request.setAttribute("token_user", token);
request.setAttribute("claims_user", claims);
}
} catch (Exception e) {
throw new RuntimeException("令牌不正確");
}
}
return true;
}
}
package com.springCloud.user.config.interceptor;
import com.springCloud.user.interceptor.JwtInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
private JwtInterceptor jwtInterceptor;
/**
* 這裏需要是 public 修飾
*
* @param jwtInterceptor jwtInterceptor
*/
@Autowired
public InterceptorConfig(JwtInterceptor jwtInterceptor) {
this.jwtInterceptor = jwtInterceptor;
}
/**
* Registered Interceptor
*
* @param registry registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 註冊攔截器要聲明攔截器對象和攔截器請求.
registry.addInterceptor(jwtInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/**/login**/**");
}
}
4. 配置
加上下面的文件防止警告
{
"properties": [
{
"name": "jwt.config.key",
"type": "java.lang.String",
"description": "Description for jwt.config.key.",
"defaultValue": "springCloud"
},
{
"name": "jwt.config.expiration",
"type": "java.lang.Long",
"description": "Description for jwt.config.expiration.",
"defaultValue": 3600000
}
]
}
在配置文件中
jwt:
config:
expiration: 3600000
key: key
5. 使用
添加
private UserService userService;
private RedisTemplate<String, String> redisTemplate;
private HttpServletRequest request;
private JWT jwt;
/**
* 獲取容器對象
*
* @param userService 識別 userService 容器對象
*/
@Autowired
private UserController(UserService userService,
RedisTemplate<String, String> redisTemplate,
HttpServletRequest request,
JWT jwt) {
this.userService = userService;
this.redisTemplate = redisTemplate;
this.request = request;
this.jwt = jwt;
}
/**
* 登錄用戶時需要前後端通話的操作 JWT
*
* @param user 用戶
* @return Result
*/
private Result login_jwt(User user) {
String token = this.jwt.createJWT(user.getId(), user.getName(), "user");
Map<String, Object> map = new HashMap<>();
map.put("id", user.getId());
map.put("role", "user");
map.put("token", token);
return new Result(StatusCode.OK, true, "用戶登錄成功", map);
}
/**
* 手機號登錄
*
* @param user 用戶
* @return Result
*/
@PostMapping("/login_phone")
public Result login_phone(@RequestBody User user) {
User login = userService.login_phone(user);
if (login == null) {
return new Result(StatusCode.LOGIN_ERROR, false, "用戶登錄失敗");
}
// 登錄成功了, 需要進行前後端通話的操作. JWT
return login_jwt(login);
}
/**
* 自動登錄
*
* @return Result
*/
@PostMapping("/authLogin")
public Result login() {
Claims token_user = (Claims) request.getAttribute("claims_user");
String id = token_user.getId();
String role = (String) token_user.get("role");
if (role == null || "".equals(role)) {
return new Result(StatusCode.LOGIN_ERROR, false, "登錄失效");
}
// 登錄成功了, 需要進行前後端通話的操作. JWT
return new Result(StatusCode.OK, true, "自動登錄成功", userService.findById(id));
}