Commit 6fe0379a authored by liming's avatar liming

feat(初始化项目): 增加jwt拦截

parent c60c749e
......@@ -30,5 +30,25 @@
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
......@@ -17,6 +17,7 @@ public enum RespCodeEnum {
DATA_CHANGE_ERROR("007", "当前数据已更新"),
LOGIN_ERROR("401", "用户名或密码错误"),
NOT_LOGIN("401", "未通过登录认证,请先进行登录"),
TOKEN_EXPIRE("401", "当前Token已过期"),
BIND_ERROR("402", "用户绑定错误"),
DATA_AUTH_ERROR("403", "没有当前功能操作权限,请联系管理员");
......
......@@ -31,7 +31,7 @@ public class Result {
private String respMsg;
private String errorCode;
private Object data;
private boolean hasNewToken;
private boolean refreshToken;
private String longToken;
private String shortToken;
......
package com.antai.sport.http.server.common.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Author liming
* @Date 2021/8/20 11:38
* @Email lmmax@126.com
* @Description:
*/
@Component
public class TokenService {
@Value("${project.jwt.secret}")
private String secret;
@Value("${project.jwt.prefix}")
private String tokenPrefix;
@Value("${project.jwt.long-token-expire}")
private long longTokenExpire;
@Value("${project.jwt.short-token-expire}")
private long shortTokenExpire;
@Value("${project.jwt.subject-key}")
private String subjectKey;
@Value("${project.jwt.long-token-key}")
private String longTokenKey;
public TokenVO initToken(String username) {
Map<String, Object> claims = new HashMap<>();
long currentTimeMillis = System.currentTimeMillis();
claims.put(subjectKey, username);
String shortToken = tokenPrefix + " " + Jwts.builder()
.setClaims(claims)
.setIssuedAt(new Date(currentTimeMillis))
.setExpiration(new Date(currentTimeMillis + shortTokenExpire))
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
claims.put(longTokenKey, true);
String longToken = tokenPrefix + " " + Jwts.builder()
.setClaims(claims)
.setIssuedAt(new Date(currentTimeMillis))
.setExpiration(new Date(currentTimeMillis + longTokenExpire))
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
return new TokenVO(longToken, shortToken);
}
public Claims validateToken(String token) {
try {
Claims claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token.replace(tokenPrefix, ""))
.getBody();
if (claims != null) {
return claims;
}
} catch (Exception ignored) {
}
return null;
}
}
package com.antai.sport.http.server.common.jwt;
/**
* @Author liming
* @Date 2021/8/22 21:48
* @Email lmmax@126.com
* @Description:
*/
public class TokenVO {
private String longToken;
private String shortToken;
public TokenVO(String longToken, String shortToken) {
this.longToken = longToken;
this.shortToken = shortToken;
}
public String getLongToken() {
return longToken;
}
public void setLongToken(String longToken) {
this.longToken = longToken;
}
public String getShortToken() {
return shortToken;
}
public void setShortToken(String shortToken) {
this.shortToken = shortToken;
}
}
\ No newline at end of file
......@@ -18,6 +18,16 @@
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.antai.sport.http.server</groupId>
......
......@@ -5,6 +5,7 @@ import com.antai.sport.http.server.game.api.business.sport.user.dto.ReqLogin;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
......@@ -20,15 +21,20 @@ import static com.antai.sport.http.server.common.base.Result.success;
* @Description:
*/
@RestController
@Api(tags={"用户相关接口"})
@Api(tags = {"用户相关接口"})
public class SportUserController {
@Resource
private SportUserService sportUserService;
@ApiOperation(value="登录接口",notes = "登录成功后返回长短token")
@ApiOperation(value = "登录接口", notes = "登录成功后返回长短token")
@PostMapping("/login")
public ResponseEntity<Result> login(@RequestBody ReqLogin param) {
return success(sportUserService.login(param));
}
@GetMapping("/test")
public ResponseEntity<Result> test() {
return success("test");
}
}
......@@ -3,6 +3,8 @@ package com.antai.sport.http.server.game.api.business.sport.user;
import com.antai.sport.http.server.common.base.Result;
import com.antai.sport.http.server.common.exception.BusinessException;
import com.antai.sport.http.server.common.jwt.TokenService;
import com.antai.sport.http.server.common.jwt.TokenVO;
import com.antai.sport.http.server.constants.DeleteStatus;
import com.antai.sport.http.server.constants.LoginMode;
import com.antai.sport.http.server.game.api.business.sport.user.dto.ReqLogin;
......@@ -27,6 +29,8 @@ public class SportUserService {
@Resource
private SportUserMapper sportUserMapper;
@Resource
private TokenService tokenService;
public Result login(ReqLogin param) {
if (param.getMode() == null || (!param.getMode().equals(LoginMode.PASSWORD) && !param.getMode().equals(LoginMode.SMS_CAPTCHA))) {
......@@ -54,6 +58,9 @@ public class SportUserService {
String hashPwd = DigestUtils.md5DigestAsHex(param.getPassword().getBytes());
if (hashPwd.equals(sportUser.getPassword())) {
result.setRespMsg("登录成功");
TokenVO tokenVO = tokenService.initToken(param.getUsername());
result.setLongToken(tokenVO.getLongToken());
result.setShortToken(tokenVO.getShortToken());
result.setData(true);
} else {
throw new BusinessException("用户名或密码错误");
......
package com.antai.sport.http.server.game.api.config;
import com.antai.sport.http.server.game.api.interceptor.TokenInterceptor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
* @Author liming
* @Date 2021/8/22 17:03
* @Email lmmax@126.com
* @Description:
*/
@Configuration
@ConfigurationProperties(prefix = "project")
public class WebMvcConfig implements WebMvcConfigurer {
private List<String> permitUrl;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor()).
addPathPatterns("/**").
excludePathPatterns(permitUrl);
}
@Bean
TokenInterceptor tokenInterceptor() {
return new TokenInterceptor();
}
public void setPermitUrl(List<String> permitUrl) {
this.permitUrl = permitUrl;
}
}
package com.antai.sport.http.server.game.api.interceptor;
import com.antai.sport.http.server.common.base.Result;
import com.antai.sport.http.server.common.jwt.TokenService;
import com.antai.sport.http.server.common.jwt.TokenVO;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.annotation.Resource;
import java.util.List;
/**
* @Author liming
* @Date 2021/8/22 18:07
* @Email lmmax@126.com
* @Description:
*/
@RestControllerAdvice(basePackages = "com.antai")
@ResponseBody
public class CustomResponseAdvice implements ResponseBodyAdvice<Object> {
@Value("${project.header-token-key}")
private String headerTokenKey;
@Value("${project.jwt.subject-key}")
private String subjectKey;
@Value("${project.jwt.long-token-key}")
private String longTokenKey;
@Resource
private TokenService tokenService;
@Override
public boolean supports(MethodParameter methodParameter,
Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public Object beforeBodyWrite(Object result, MethodParameter methodParameter,
MediaType mediaType,
Class<? extends HttpMessageConverter<?>> aClass,
ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse) {
if (!(result instanceof Result)) {
return result;
}
String token;
List<String> tokenList = serverHttpRequest.getHeaders().get(headerTokenKey);
if (tokenList != null && !tokenList.isEmpty()) {
token = tokenList.get(0);
if (!StringUtils.isBlank(token)) {
Claims claims = tokenService.validateToken(token);
if (claims != null && claims.containsKey(longTokenKey)) {
Result realResult = (Result) result;
TokenVO tokenVO = tokenService.initToken(claims.get(subjectKey).toString());
realResult.setRefreshToken(true);
realResult.setLongToken(tokenVO.getLongToken());
realResult.setShortToken(tokenVO.getShortToken());
}
}
}
return result;
}
}
package com.antai.sport.http.server.game.api.interceptor;
import com.antai.sport.http.server.common.jwt.TokenService;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
public class TokenInterceptor implements HandlerInterceptor {
@Value("${project.header-token-key}")
private String headerTokenKey;
@Resource
private TokenService tokenService;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader(headerTokenKey);
if (null == token) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, UNAUTHORIZED.getReasonPhrase());
return false;
}
Claims claims = tokenService.validateToken(token);
if (claims == null) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, UNAUTHORIZED.getReasonPhrase());
return false;
}
return true;
}
}
......@@ -8,6 +8,21 @@ spring:
project:
header-token-key: Authorization
jwt:
subject-key: phone
long-token-key: longToken
secret: antaikeji666
prefix: Bearer
long-token-expire: 2_592_000_000
short-token-expire: 7_200_000
permit-url:
- /swagger**/**
- /webjars/**
- /doc.html
- /v3/**
- /favicon.ico
- /error
- /login
swagger:
enable: false
......
......@@ -31,6 +31,9 @@
<yaml.version>1.28</yaml.version>
<swagger.version>3.0.0</swagger.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jjwt.version>0.7.0</jjwt.version>
<jaxb.version>2.3.0</jaxb.version>
<activation.version>1.1.1</activation.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
......@@ -67,6 +70,31 @@
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>${activation.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment