本文抄襲自 https://www.jianshu.com/p/e88d3f8151db
本文在 使用IDEA快速搭建基於Maven的SpringBoot項目(集成使用Redis) 基礎上繼續
引入JWT依賴
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency>
自定義兩個注解
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface UserLoginToken { boolean required() default true; }
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface PassToken { boolean required() default true; }
登錄用戶類
public class LoginUser implements Serializable { String id; String username; String password; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
攔截器
package com.blaze.demo.interceptor; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.exceptions.JWTVerificationException; import com.blaze.demo.annotation.PassToken; import com.blaze.demo.annotation.UserLoginToken; import com.blaze.demo.model.LoginUser; import com.blaze.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; public class AuthenticationInterceptor implements HandlerInterceptor { @Autowired UserService userService; @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception { String token = httpServletRequest.getHeader("token");// 從 http 請求頭中取出 token // 如果不是映射到方法直接通過 if(!(object instanceof HandlerMethod)){ return true; } HandlerMethod handlerMethod=(HandlerMethod)object; Method method=handlerMethod.getMethod(); //檢查是否有passtoken注釋,有則跳過認證 if (method.isAnnotationPresent(PassToken.class)) { PassToken passToken = method.getAnnotation(PassToken.class); if (passToken.required()) { return true; } } //檢查有沒有需要用戶權限的注解 if (method.isAnnotationPresent(UserLoginToken.class)) { UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class); if (userLoginToken.required()) { // 執行認證 if (token == null) { throw new RuntimeException("無token,請重新登錄"); } // 獲取 token 中的 user id String userId; try { userId = JWT.decode(token).getAudience().get(0); } catch (JWTDecodeException j) { throw new RuntimeException("401"); } LoginUser user = userService.findUserById(userId); if (user == null) { throw new RuntimeException("用戶不存在,請重新登錄"); } // 驗證 token JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build(); try { jwtVerifier.verify(token); } catch (JWTVerificationException e) { throw new RuntimeException("401"); } return true; } } return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
配置攔截器
package com.blaze.demo.config; import com.blaze.demo.interceptor.AuthenticationInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class InterceptorConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authenticationInterceptor()) .addPathPatterns("/**"); // 攔截所有請求,通過判斷是否有 @LoginRequired 注解 決定是否需要登錄 } @Bean public AuthenticationInterceptor authenticationInterceptor() { return new AuthenticationInterceptor(); } }
接口Controller
@GetMapping("/test01")
public String test01() {
return "不需要token";
}
@UserLoginToken
@GetMapping("/test02")
public String test02() {
return "需要token";
}
@ResponseBody
@PostMapping("/login")
public Object login(@ApiParam(value = "賬號") @RequestParam String account,
@ApiParam(value = "密碼") @RequestParam String password) {
JSONObject jsonObject = new JSONObject();
LoginUser userForBase = userService.queryAdminByAccount(account);
if (userForBase == null) {
jsonObject.put("message", "登錄失敗,用戶不存在");
return jsonObject;
} else {
if (!userForBase.getPassword().equals(password)) {
jsonObject.put("message", "登錄失敗,密碼錯誤");
return jsonObject;
} else {
String token = getToken(userForBase);
jsonObject.put("token", token);
jsonObject.put("user", userForBase);
return jsonObject;
}
}
}
public static String getToken(LoginUser user) {
String token = "";
token = JWT.create().withAudience(user.getId())
.sign(Algorithm.HMAC256(user.getPassword()));
return token;
}
