pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
</dependencies>
工程结构:
application.properties(spring-boot配置):
server.port=7778
server.servlet.context-path=/access-token
spring.datasource.url = jdbc:mysql://127.0.0.1/cxx?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = root1234!
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.minimum-idle = 5
spring.datasource.idle-timeout = 18000
spring.datasource.maximum-pool-size = 10
spring.datasource.auto-commit = true
spring.datasource.max-lifetime = 0
pagehelper.helperDialect = mysql
mybatis-plus.mapperLocations = classpath:mapper/*.xml
mybatis-plus.configuration.call-setters-on-nulls = true
mybatis-plus.typeAliasesPackage = com.example.access.token.entity
User:
package com.example.access.token.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
String id;
String username;
String password;
}
UserMapper:
package com.example.access.token.mapper;
import com.example.access.token.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
@Mapper
@Component
public interface UserMapper {
User findByUsername(String username);
User findUserById(String id);
}
UserService:
package com.example.access.token.service;
import com.example.access.token.entity.User;
import com.example.access.token.mapper.UserMapper;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserMapper userMapper;
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
public User findByUsername(User user){
return userMapper.findByUsername(user.getUsername());
}
public User findUserById(String userId) {
return userMapper.findUserById(userId);
}
}
PassToken(自定义注解,跳过token验证):
package com.example.access.token.target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
boolean required() default true;
}
UserLoginToken(自定义注解,需要token验证):
package com.example.access.token.target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
boolean required() default true;
}
AuthenticationInterceptor:
package com.example.access.token.tokenInit;
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.example.access.token.entity.User;
import com.example.access.token.service.UserService;
import com.example.access.token.target.PassToken;
import com.example.access.token.target.UserLoginToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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
private UserService userService;
private static final Logger log = LoggerFactory.getLogger(AuthenticationInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) {
String token = httpServletRequest.getHeader("token");
if (!(object instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) object;
Method method = handlerMethod.getMethod();
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) {
log.error("token is null");
throw new RuntimeException("401");
}
String userId;
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
log.error("401");
throw new RuntimeException("401");
}
User user = userService.findUserById(userId);
if (user == null) {
log.error("user is null");
throw new RuntimeException("401");
}
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
log.error("401");
throw new RuntimeException("401");
}
return true;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
}
}
InterceptorConfig:
package com.example.access.token.tokenInit;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;
import java.util.List;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**"); // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
}
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> arg0) {
// TODO Auto-generated method stub
}
@Override
public void addCorsMappings(CorsRegistry arg0) {
// TODO Auto-generated method stub
}
@Override
public void addFormatters(FormatterRegistry arg0) {
// TODO Auto-generated method stub
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry arg0) {
// TODO Auto-generated method stub
}
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> arg0) {
// TODO Auto-generated method stub
}
@Override
public void addViewControllers(ViewControllerRegistry arg0) {
// TODO Auto-generated method stub
}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer arg0) {
// TODO Auto-generated method stub
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer arg0) {
// TODO Auto-generated method stub
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer arg0) {
// TODO Auto-generated method stub
}
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> arg0) {
// TODO Auto-generated method stub
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> arg0) {
// TODO Auto-generated method stub
}
@Override
public void configurePathMatch(PathMatchConfigurer arg0) {
// TODO Auto-generated method stub
}
@Override
public void configureViewResolvers(ViewResolverRegistry arg0) {
// TODO Auto-generated method stub
}
@Override
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> arg0) {
// TODO Auto-generated method stub
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> arg0) {
// TODO Auto-generated method stub
}
@Override
public MessageCodesResolver getMessageCodesResolver() {
// TODO Auto-generated method stub
return null;
}
@Override
public Validator getValidator() {
// TODO Auto-generated method stub
return null;
}
}
TokenInit:
package com.example.access.token.tokenInit;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.example.access.token.entity.User;
import java.util.Date;
public class TokenInit {
public static String getToken (User user) {
Date start = new Date();
long currentTime = System.currentTimeMillis() +60*60*1000;//一小时有效时间
Date end = new Date(currentTime);
return JWT.create().withIssuedAt(start).withExpiresAt(end).withAudience(user.getId())
.sign(Algorithm.HMAC256(user.getPassword()));
}
}
TokenUtil:
package com.example.access.token.tokenInit;
import com.auth0.jwt.JWT;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
public class TokenUtil {
public static String getTokenUserId() {
String token = getRequest().getHeader("token");// 从 http 请求头中取出 token
String userId = null;
try{
userId = JWT.decode(token).getAudience().get(0);
}catch (Exception e) {
System.out.println(e.toString());
}
return userId;
}
public static long time () {
String token = getRequest().getHeader("token");// 从 http 请求头中取出 token
long st = 0;
try{
st = JWT.decode(token).getIssuedAt().getTime();
}catch (Exception e) {
System.out.println(e.toString());
}
return System.currentTimeMillis()-st;
}
public static HttpServletRequest getRequest() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
return requestAttributes == null ? null : requestAttributes.getRequest();
}
}
UserMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.access.token.mapper.UserMapper">
<select id="findByUsername" parameterType="String" resultType="com.example.access.token.entity.User">
SELECT id,password,username
FROM user
WHERE
username=#{username}
</select>
<select id="findUserById" parameterType="String" resultType="com.example.access.token.entity.User">
SELECT id,username,password
FROM user
WHERE
id=#{id}
</select>
</mapper>
GlobalExceptionHandler(自定义公共异常类):
package com.example.access.token.api;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(Exception.class)
public Object handleException(Exception e) {
String msg = e.getMessage();
if (msg == null || msg.equals("")) {
msg = "server is error";
}
JSONObject js = new JSONObject();
js.put("success",false);
js.put("message", msg);
return js;
}
}
UserApi(测试接口):
package com.example.access.token.api;
import com.alibaba.fastjson.JSONObject;
import com.example.access.token.entity.User;
import com.example.access.token.service.UserService;
import com.example.access.token.target.PassToken;
import com.example.access.token.target.UserLoginToken;
import com.example.access.token.tokenInit.TokenInit;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/userApi")
public class UserApi {
final UserService userService;
public UserApi(UserService userService) {
this.userService = userService;
}
@PostMapping("/getToken")
public Object getToken(@RequestBody User user) {
JSONObject js = new JSONObject();
User userForBase = userService.findByUsername(user);
js.put("success", true);
js.put("message", "login authorization success");
js.put("token", "");
if (userForBase == null) {
js.put("success", false);
js.put("message", "user is null");
} else {
if (!userForBase.getPassword().equals(user.getPassword())) {
js.put("success", false);
js.put("message", "password is error");
} else {
String token = TokenInit.getToken(userForBase);
js.put("token", token);
}
}
return js;
}
@UserLoginToken
@GetMapping("/getMessage")
public String getMessage() {
return "你已通过验证";
}
@PassToken
@GetMapping("/getMessage0")
public String getMessage0() {
return "你已通过验证";
}
}