mirror of
https://github.com/PlayEdu/PlayEdu
synced 2025-07-24 02:09:35 +08:00
接入sa-token
This commit is contained in:
parent
5005e76b81
commit
c9371b0589
19
pom.xml
19
pom.xml
@ -138,6 +138,25 @@
|
|||||||
<version>5.8.16</version>
|
<version>5.8.16</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||||
|
<version>1.34.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-dao-redis-jackson</artifactId>
|
||||||
|
<version>1.34.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Sa-Token 整合 jwt -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-jwt</artifactId>
|
||||||
|
<version>1.34.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springdoc</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
|
@ -19,11 +19,6 @@ import xyz.playedu.api.domain.User;
|
|||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* @create 2023/3/13 09:24
|
|
||||||
*/
|
|
||||||
public class FCtx {
|
public class FCtx {
|
||||||
private static final java.lang.ThreadLocal<LinkedHashMap<String, Object>> THREAD_LOCAL =
|
private static final java.lang.ThreadLocal<LinkedHashMap<String, Object>> THREAD_LOCAL =
|
||||||
new java.lang.ThreadLocal<>();
|
new java.lang.ThreadLocal<>();
|
||||||
|
@ -13,14 +13,16 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package xyz.playedu.api.types;
|
package xyz.playedu.api.config;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
@Data
|
@Data
|
||||||
public class JwtToken {
|
public class AuthConfig {
|
||||||
|
@Value("${sa-token.timeout}")
|
||||||
private String token;
|
private Integer expired;
|
||||||
|
|
||||||
private Long expire;
|
|
||||||
}
|
}
|
31
src/main/java/xyz/playedu/api/config/SaTokenConfigure.java
Normal file
31
src/main/java/xyz/playedu/api/config/SaTokenConfigure.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 杭州白书科技有限公司
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package xyz.playedu.api.config;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
|
||||||
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SaTokenConfigure {
|
||||||
|
// Sa-Token 整合 jwt (Simple 简单模式)
|
||||||
|
@Bean
|
||||||
|
public StpLogic getStpLogicJwt() {
|
||||||
|
return new StpLogicJwtForSimple();
|
||||||
|
}
|
||||||
|
}
|
@ -37,11 +37,11 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class ExceptionController {
|
public class ExceptionController {
|
||||||
|
|
||||||
@ExceptionHandler(Exception.class)
|
// @ExceptionHandler(Exception.class)
|
||||||
public JsonResponse exceptionHandler(Exception e) {
|
// public JsonResponse exceptionHandler(Exception e) {
|
||||||
log.error(e.getMessage());
|
// log.error(e.getMessage());
|
||||||
return JsonResponse.error("系统错误", 500);
|
// return JsonResponse.error("系统错误", 500);
|
||||||
}
|
// }
|
||||||
|
|
||||||
@ExceptionHandler(ServiceException.class)
|
@ExceptionHandler(ServiceException.class)
|
||||||
public JsonResponse serviceExceptionHandler(ServiceException e) {
|
public JsonResponse serviceExceptionHandler(ServiceException e) {
|
||||||
|
@ -23,7 +23,6 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import xyz.playedu.api.BCtx;
|
import xyz.playedu.api.BCtx;
|
||||||
import xyz.playedu.api.bus.BackendBus;
|
import xyz.playedu.api.bus.BackendBus;
|
||||||
import xyz.playedu.api.constant.BPermissionConstant;
|
import xyz.playedu.api.constant.BPermissionConstant;
|
||||||
import xyz.playedu.api.constant.SystemConstant;
|
|
||||||
import xyz.playedu.api.domain.AdminUser;
|
import xyz.playedu.api.domain.AdminUser;
|
||||||
import xyz.playedu.api.event.AdminUserLoginEvent;
|
import xyz.playedu.api.event.AdminUserLoginEvent;
|
||||||
import xyz.playedu.api.exception.JwtLogoutException;
|
import xyz.playedu.api.exception.JwtLogoutException;
|
||||||
@ -32,9 +31,8 @@ import xyz.playedu.api.middleware.ImageCaptchaCheckMiddleware;
|
|||||||
import xyz.playedu.api.request.backend.LoginRequest;
|
import xyz.playedu.api.request.backend.LoginRequest;
|
||||||
import xyz.playedu.api.request.backend.PasswordChangeRequest;
|
import xyz.playedu.api.request.backend.PasswordChangeRequest;
|
||||||
import xyz.playedu.api.service.AdminUserService;
|
import xyz.playedu.api.service.AdminUserService;
|
||||||
import xyz.playedu.api.service.JWTService;
|
import xyz.playedu.api.service.BackendAuthService;
|
||||||
import xyz.playedu.api.types.JsonResponse;
|
import xyz.playedu.api.types.JsonResponse;
|
||||||
import xyz.playedu.api.types.JwtToken;
|
|
||||||
import xyz.playedu.api.util.HelperUtil;
|
import xyz.playedu.api.util.HelperUtil;
|
||||||
import xyz.playedu.api.util.IpUtil;
|
import xyz.playedu.api.util.IpUtil;
|
||||||
import xyz.playedu.api.util.RequestUtil;
|
import xyz.playedu.api.util.RequestUtil;
|
||||||
@ -49,7 +47,7 @@ public class LoginController {
|
|||||||
|
|
||||||
@Autowired private BackendBus backendBus;
|
@Autowired private BackendBus backendBus;
|
||||||
|
|
||||||
@Autowired private JWTService jwtService;
|
@Autowired private BackendAuthService authService;
|
||||||
|
|
||||||
@Autowired private ApplicationContext ctx;
|
@Autowired private ApplicationContext ctx;
|
||||||
|
|
||||||
@ -69,19 +67,16 @@ public class LoginController {
|
|||||||
return JsonResponse.error("当前用户已禁止登录");
|
return JsonResponse.error("当前用户已禁止登录");
|
||||||
}
|
}
|
||||||
|
|
||||||
String url = RequestUtil.url();
|
String token = authService.loginUsingId(adminUser.getId(), RequestUtil.url());
|
||||||
JwtToken token =
|
|
||||||
jwtService.generate(adminUser.getId(), url, SystemConstant.JWT_PRV_ADMIN_USER);
|
|
||||||
|
|
||||||
HashMap<String, Object> data = new HashMap<>();
|
HashMap<String, Object> data = new HashMap<>();
|
||||||
data.put("token", token.getToken());
|
data.put("token", token);
|
||||||
data.put("expire", token.getExpire());
|
|
||||||
|
|
||||||
ctx.publishEvent(
|
ctx.publishEvent(
|
||||||
new AdminUserLoginEvent(
|
new AdminUserLoginEvent(
|
||||||
this,
|
this,
|
||||||
adminUser.getId(),
|
adminUser.getId(),
|
||||||
token.getToken(),
|
token,
|
||||||
IpUtil.getIpAddress(),
|
IpUtil.getIpAddress(),
|
||||||
adminUser.getLoginTimes()));
|
adminUser.getLoginTimes()));
|
||||||
|
|
||||||
@ -90,7 +85,7 @@ public class LoginController {
|
|||||||
|
|
||||||
@PostMapping("/logout")
|
@PostMapping("/logout")
|
||||||
public JsonResponse logout() throws JwtLogoutException {
|
public JsonResponse logout() throws JwtLogoutException {
|
||||||
jwtService.adminUserLogout(RequestUtil.token());
|
authService.logout();
|
||||||
return JsonResponse.success("success");
|
return JsonResponse.success("success");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,36 +24,28 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import xyz.playedu.api.FCtx;
|
import xyz.playedu.api.FCtx;
|
||||||
import xyz.playedu.api.constant.SystemConstant;
|
|
||||||
import xyz.playedu.api.domain.User;
|
import xyz.playedu.api.domain.User;
|
||||||
import xyz.playedu.api.event.UserLoginEvent;
|
import xyz.playedu.api.event.UserLoginEvent;
|
||||||
import xyz.playedu.api.event.UserLogoutEvent;
|
import xyz.playedu.api.event.UserLogoutEvent;
|
||||||
import xyz.playedu.api.exception.JwtLogoutException;
|
|
||||||
import xyz.playedu.api.exception.LimitException;
|
import xyz.playedu.api.exception.LimitException;
|
||||||
import xyz.playedu.api.middleware.ImageCaptchaCheckMiddleware;
|
import xyz.playedu.api.middleware.ImageCaptchaCheckMiddleware;
|
||||||
import xyz.playedu.api.request.frontend.LoginPasswordRequest;
|
import xyz.playedu.api.request.frontend.LoginPasswordRequest;
|
||||||
import xyz.playedu.api.service.JWTService;
|
import xyz.playedu.api.service.FrontendAuthService;
|
||||||
import xyz.playedu.api.service.UserService;
|
import xyz.playedu.api.service.UserService;
|
||||||
import xyz.playedu.api.types.JsonResponse;
|
import xyz.playedu.api.types.JsonResponse;
|
||||||
import xyz.playedu.api.types.JwtToken;
|
|
||||||
import xyz.playedu.api.util.HelperUtil;
|
import xyz.playedu.api.util.HelperUtil;
|
||||||
import xyz.playedu.api.util.IpUtil;
|
import xyz.playedu.api.util.IpUtil;
|
||||||
import xyz.playedu.api.util.RequestUtil;
|
import xyz.playedu.api.util.RequestUtil;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* @create 2023/3/2 21:51
|
|
||||||
*/
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/auth/login")
|
@RequestMapping("/api/v1/auth/login")
|
||||||
public class LoginController {
|
public class LoginController {
|
||||||
|
|
||||||
@Autowired private UserService userService;
|
@Autowired private UserService userService;
|
||||||
|
|
||||||
@Autowired private JWTService jwtService;
|
@Autowired private FrontendAuthService authService;
|
||||||
|
|
||||||
@Autowired private ApplicationContext ctx;
|
@Autowired private ApplicationContext ctx;
|
||||||
|
|
||||||
@ -74,19 +66,17 @@ public class LoginController {
|
|||||||
return JsonResponse.error("当前学员已锁定无法登录");
|
return JsonResponse.error("当前学员已锁定无法登录");
|
||||||
}
|
}
|
||||||
|
|
||||||
JwtToken token =
|
String token = authService.loginUsingId(user.getId(), RequestUtil.url());
|
||||||
jwtService.generate(user.getId(), RequestUtil.url(), SystemConstant.JWT_PRV_USER);
|
|
||||||
|
|
||||||
HashMap<String, Object> data = new HashMap<>();
|
HashMap<String, Object> data = new HashMap<>();
|
||||||
data.put("token", token.getToken());
|
data.put("token", token);
|
||||||
data.put("expired", token.getExpire());
|
|
||||||
|
|
||||||
ctx.publishEvent(
|
ctx.publishEvent(
|
||||||
new UserLoginEvent(
|
new UserLoginEvent(
|
||||||
this,
|
this,
|
||||||
user.getId(),
|
user.getId(),
|
||||||
user.getEmail(),
|
user.getEmail(),
|
||||||
token.getToken(),
|
token,
|
||||||
IpUtil.getIpAddress(),
|
IpUtil.getIpAddress(),
|
||||||
RequestUtil.ua()));
|
RequestUtil.ua()));
|
||||||
|
|
||||||
@ -94,8 +84,8 @@ public class LoginController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/logout")
|
@PostMapping("/logout")
|
||||||
public JsonResponse logout() throws JwtLogoutException {
|
public JsonResponse logout() {
|
||||||
jwtService.userLogout(RequestUtil.token());
|
authService.logout();
|
||||||
ctx.publishEvent(new UserLogoutEvent(this, FCtx.getId(), FCtx.getJwtJti()));
|
ctx.publishEvent(new UserLogoutEvent(this, FCtx.getId(), FCtx.getJwtJti()));
|
||||||
return JsonResponse.success();
|
return JsonResponse.success();
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,11 @@ public class UserController {
|
|||||||
@GetMapping("/detail")
|
@GetMapping("/detail")
|
||||||
public JsonResponse detail() {
|
public JsonResponse detail() {
|
||||||
User user = FCtx.getUser();
|
User user = FCtx.getUser();
|
||||||
List<Department> departments =
|
List<Department> departments = new ArrayList<>();
|
||||||
departmentService.listByIds(userService.getDepIdsByUserId(user.getId()));
|
List<Integer> depIds = userService.getDepIdsByUserId(user.getId());
|
||||||
|
if (depIds != null && depIds.size() > 0) {
|
||||||
|
departmentService.listByIds(depIds);
|
||||||
|
}
|
||||||
|
|
||||||
user.setIdCard(PrivacyUtil.hideIDCard(user.getIdCard()));
|
user.setIdCard(PrivacyUtil.hideIDCard(user.getIdCard()));
|
||||||
|
|
||||||
|
@ -22,36 +22,34 @@ import org.springframework.context.event.EventListener;
|
|||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import xyz.playedu.api.constant.SystemConstant;
|
|
||||||
import xyz.playedu.api.event.UserLoginEvent;
|
import xyz.playedu.api.event.UserLoginEvent;
|
||||||
import xyz.playedu.api.exception.JwtLogoutException;
|
import xyz.playedu.api.service.FrontendAuthService;
|
||||||
import xyz.playedu.api.service.JWTService;
|
|
||||||
import xyz.playedu.api.service.UserLoginRecordService;
|
import xyz.playedu.api.service.UserLoginRecordService;
|
||||||
import xyz.playedu.api.types.JWTPayload;
|
|
||||||
import xyz.playedu.api.util.IpUtil;
|
import xyz.playedu.api.util.IpUtil;
|
||||||
|
|
||||||
/**
|
import java.util.HashMap;
|
||||||
* @Author 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* @create 2023/3/10 13:45
|
|
||||||
*/
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class UserLoginListener {
|
public class UserLoginListener {
|
||||||
|
|
||||||
@Autowired private UserLoginRecordService loginRecordService;
|
@Autowired private UserLoginRecordService loginRecordService;
|
||||||
|
|
||||||
@Autowired private JWTService jwtService;
|
@Autowired private FrontendAuthService authService;
|
||||||
|
|
||||||
@Async
|
@Async
|
||||||
@EventListener
|
@EventListener
|
||||||
public void updateLoginInfo(UserLoginEvent event) throws JwtLogoutException {
|
public void updateLoginInfo(UserLoginEvent event) {
|
||||||
String ipArea = IpUtil.getRealAddressByIP(event.getIp());
|
String ipArea = IpUtil.getRealAddressByIP(event.getIp());
|
||||||
JWTPayload payload = jwtService.parse(event.getToken(), SystemConstant.JWT_PRV_USER);
|
|
||||||
|
HashMap<String, String> tokenData = authService.parse(event.getToken());
|
||||||
|
String jti = tokenData.get("jti");
|
||||||
|
Long exp = Long.parseLong(tokenData.get("exp"));
|
||||||
|
|
||||||
loginRecordService.store(
|
loginRecordService.store(
|
||||||
event.getUserId(),
|
event.getUserId(),
|
||||||
payload.getJti(),
|
jti,
|
||||||
payload.getExp(),
|
exp,
|
||||||
event.getIp(),
|
event.getIp(),
|
||||||
ipArea,
|
ipArea,
|
||||||
event.getUserAgent().getBrowser().toString(),
|
event.getUserAgent().getBrowser().toString(),
|
||||||
|
@ -27,15 +27,12 @@ import org.springframework.web.servlet.HandlerInterceptor;
|
|||||||
import xyz.playedu.api.BCtx;
|
import xyz.playedu.api.BCtx;
|
||||||
import xyz.playedu.api.bus.AppBus;
|
import xyz.playedu.api.bus.AppBus;
|
||||||
import xyz.playedu.api.bus.BackendBus;
|
import xyz.playedu.api.bus.BackendBus;
|
||||||
import xyz.playedu.api.constant.SystemConstant;
|
|
||||||
import xyz.playedu.api.domain.AdminUser;
|
import xyz.playedu.api.domain.AdminUser;
|
||||||
import xyz.playedu.api.service.AdminUserService;
|
import xyz.playedu.api.service.AdminUserService;
|
||||||
import xyz.playedu.api.service.AppConfigService;
|
import xyz.playedu.api.service.AppConfigService;
|
||||||
import xyz.playedu.api.service.JWTService;
|
import xyz.playedu.api.service.BackendAuthService;
|
||||||
import xyz.playedu.api.types.JWTPayload;
|
|
||||||
import xyz.playedu.api.types.JsonResponse;
|
import xyz.playedu.api.types.JsonResponse;
|
||||||
import xyz.playedu.api.util.HelperUtil;
|
import xyz.playedu.api.util.HelperUtil;
|
||||||
import xyz.playedu.api.util.RequestUtil;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -44,7 +41,7 @@ import java.util.Map;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class AdminMiddleware implements HandlerInterceptor {
|
public class AdminMiddleware implements HandlerInterceptor {
|
||||||
|
|
||||||
@Autowired private JWTService jwtService;
|
@Autowired private BackendAuthService authService;
|
||||||
|
|
||||||
@Autowired private AdminUserService adminUserService;
|
@Autowired private AdminUserService adminUserService;
|
||||||
|
|
||||||
@ -70,15 +67,11 @@ public class AdminMiddleware implements HandlerInterceptor {
|
|||||||
return HandlerInterceptor.super.preHandle(request, response, handler);
|
return HandlerInterceptor.super.preHandle(request, response, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
String token = RequestUtil.token();
|
if (!authService.check()) {
|
||||||
if (token.length() == 0) {
|
|
||||||
return responseTransform(response, 401, "请登录");
|
return responseTransform(response, 401, "请登录");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
AdminUser adminUser = adminUserService.findById(authService.userId());
|
||||||
JWTPayload payload = jwtService.parse(token, SystemConstant.JWT_PRV_ADMIN_USER);
|
|
||||||
|
|
||||||
AdminUser adminUser = adminUserService.findById(payload.getSub());
|
|
||||||
if (adminUser == null) {
|
if (adminUser == null) {
|
||||||
return responseTransform(response, 401, "管理员不存在");
|
return responseTransform(response, 401, "管理员不存在");
|
||||||
}
|
}
|
||||||
@ -86,17 +79,11 @@ public class AdminMiddleware implements HandlerInterceptor {
|
|||||||
return responseTransform(response, 403, "当前管理员禁止登录");
|
return responseTransform(response, 403, "当前管理员禁止登录");
|
||||||
}
|
}
|
||||||
|
|
||||||
BCtx.setId(payload.getSub());
|
BCtx.setId(authService.userId());
|
||||||
BCtx.setAdminUser(adminUser);
|
BCtx.setAdminUser(adminUser);
|
||||||
BCtx.setAdminPer(backendBus.adminUserPermissions(adminUser.getId()));
|
BCtx.setAdminPer(backendBus.adminUserPermissions(adminUser.getId()));
|
||||||
|
|
||||||
return HandlerInterceptor.super.preHandle(request, response, handler);
|
return HandlerInterceptor.super.preHandle(request, response, handler);
|
||||||
} catch (Exception e) {
|
|
||||||
if (appBus.isDev()) {
|
|
||||||
log.debug("jwt解析失败:" + e.getMessage());
|
|
||||||
}
|
|
||||||
return responseTransform(response, 401, "请重新登录");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean responseTransform(HttpServletResponse response, int code, String msg)
|
private boolean responseTransform(HttpServletResponse response, int code, String msg)
|
||||||
|
@ -26,27 +26,19 @@ import org.springframework.web.servlet.HandlerInterceptor;
|
|||||||
|
|
||||||
import xyz.playedu.api.FCtx;
|
import xyz.playedu.api.FCtx;
|
||||||
import xyz.playedu.api.constant.FrontendConstant;
|
import xyz.playedu.api.constant.FrontendConstant;
|
||||||
import xyz.playedu.api.constant.SystemConstant;
|
|
||||||
import xyz.playedu.api.domain.User;
|
import xyz.playedu.api.domain.User;
|
||||||
import xyz.playedu.api.service.JWTService;
|
import xyz.playedu.api.service.FrontendAuthService;
|
||||||
import xyz.playedu.api.service.UserService;
|
import xyz.playedu.api.service.UserService;
|
||||||
import xyz.playedu.api.types.JWTPayload;
|
|
||||||
import xyz.playedu.api.types.JsonResponse;
|
import xyz.playedu.api.types.JsonResponse;
|
||||||
import xyz.playedu.api.util.HelperUtil;
|
import xyz.playedu.api.util.HelperUtil;
|
||||||
import xyz.playedu.api.util.RequestUtil;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
|
||||||
* @Author 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* @create 2023/3/13 09:40
|
|
||||||
*/
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FrontMiddleware implements HandlerInterceptor {
|
public class FrontMiddleware implements HandlerInterceptor {
|
||||||
|
|
||||||
@Autowired private JWTService jwtService;
|
@Autowired private FrontendAuthService authService;
|
||||||
|
|
||||||
@Autowired private UserService userService;
|
@Autowired private UserService userService;
|
||||||
|
|
||||||
@ -62,15 +54,11 @@ public class FrontMiddleware implements HandlerInterceptor {
|
|||||||
return HandlerInterceptor.super.preHandle(request, response, handler);
|
return HandlerInterceptor.super.preHandle(request, response, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
String token = RequestUtil.token();
|
if (!authService.check()) {
|
||||||
if (token.length() == 0) {
|
|
||||||
return responseTransform(response, 401, "请登录");
|
return responseTransform(response, 401, "请登录");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
User user = userService.find(authService.userId());
|
||||||
JWTPayload payload = jwtService.parse(token, SystemConstant.JWT_PRV_USER);
|
|
||||||
|
|
||||||
User user = userService.find(payload.getSub());
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
return responseTransform(response, 401, "请重新登录");
|
return responseTransform(response, 401, "请重新登录");
|
||||||
}
|
}
|
||||||
@ -80,13 +68,9 @@ public class FrontMiddleware implements HandlerInterceptor {
|
|||||||
|
|
||||||
FCtx.setUser(user);
|
FCtx.setUser(user);
|
||||||
FCtx.setId(user.getId());
|
FCtx.setId(user.getId());
|
||||||
FCtx.setJWtJti(payload.getJti());
|
FCtx.setJWtJti(authService.jti());
|
||||||
|
|
||||||
return HandlerInterceptor.super.preHandle(request, response, handler);
|
return HandlerInterceptor.super.preHandle(request, response, handler);
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
return responseTransform(response, 401, "请重新登录");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean responseTransform(HttpServletResponse response, int code, String msg)
|
private boolean responseTransform(HttpServletResponse response, int code, String msg)
|
||||||
|
@ -13,34 +13,22 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package xyz.playedu.api.types;
|
package xyz.playedu.api.service;
|
||||||
|
|
||||||
import lombok.Data;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
public interface AuthService {
|
||||||
* @see https://www.rfc-editor.org/rfc/rfc7519#section-4.1
|
String loginUsingId(Integer userId, String loginUrl, String prv);
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class JWTPayload {
|
|
||||||
|
|
||||||
/** subject */
|
boolean check(String prv);
|
||||||
private Integer sub;
|
|
||||||
|
|
||||||
/** Issued At */
|
Integer userId();
|
||||||
private Long iat;
|
|
||||||
|
|
||||||
/** Expiration Time */
|
void logout();
|
||||||
private Long exp;
|
|
||||||
|
|
||||||
/** Not Before */
|
String jti();
|
||||||
private Long nbf;
|
|
||||||
|
|
||||||
/** JWT ID */
|
Long expired();
|
||||||
private String jti;
|
|
||||||
|
|
||||||
/** Issuer */
|
HashMap<String, String> parse(String token);
|
||||||
private String iss;
|
|
||||||
|
|
||||||
/** Payload */
|
|
||||||
private String prv;
|
|
||||||
}
|
}
|
@ -15,20 +15,18 @@
|
|||||||
*/
|
*/
|
||||||
package xyz.playedu.api.service;
|
package xyz.playedu.api.service;
|
||||||
|
|
||||||
import xyz.playedu.api.exception.JwtLogoutException;
|
import java.util.HashMap;
|
||||||
import xyz.playedu.api.types.JWTPayload;
|
|
||||||
import xyz.playedu.api.types.JwtToken;
|
|
||||||
|
|
||||||
public interface JWTService {
|
public interface BackendAuthService {
|
||||||
JwtToken generate(Integer userId, String iss, String prv);
|
String loginUsingId(Integer userId, String loginUrl);
|
||||||
|
|
||||||
boolean isInBlack(String jti);
|
boolean check();
|
||||||
|
|
||||||
void logout(String token, String prv) throws JwtLogoutException;
|
Integer userId();
|
||||||
|
|
||||||
void userLogout(String token) throws JwtLogoutException;
|
void logout();
|
||||||
|
|
||||||
void adminUserLogout(String token) throws JwtLogoutException;
|
String jti();
|
||||||
|
|
||||||
JWTPayload parse(String token, String prv) throws JwtLogoutException;
|
HashMap<String, String> parse(String token);
|
||||||
}
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 杭州白书科技有限公司
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package xyz.playedu.api.service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public interface FrontendAuthService {
|
||||||
|
String loginUsingId(Integer userId, String loginUrl);
|
||||||
|
|
||||||
|
boolean check();
|
||||||
|
|
||||||
|
Integer userId();
|
||||||
|
|
||||||
|
void logout();
|
||||||
|
|
||||||
|
String jti();
|
||||||
|
|
||||||
|
HashMap<String, String> parse(String token);
|
||||||
|
}
|
@ -19,11 +19,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
|
|
||||||
import xyz.playedu.api.domain.UserLoginRecord;
|
import xyz.playedu.api.domain.UserLoginRecord;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author tengteng
|
|
||||||
* @description 针对表【user_login_records】的数据库操作Service
|
|
||||||
* @createDate 2023-03-10 13:40:33
|
|
||||||
*/
|
|
||||||
public interface UserLoginRecordService extends IService<UserLoginRecord> {
|
public interface UserLoginRecordService extends IService<UserLoginRecord> {
|
||||||
UserLoginRecord store(
|
UserLoginRecord store(
|
||||||
Integer userId,
|
Integer userId,
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 杭州白书科技有限公司
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package xyz.playedu.api.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.SaLoginConfig;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import xyz.playedu.api.config.AuthConfig;
|
||||||
|
import xyz.playedu.api.service.AuthService;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class AuthServiceImpl implements AuthService {
|
||||||
|
|
||||||
|
@Autowired private AuthConfig authConfig;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String loginUsingId(Integer userId, String loginUrl, String prv) {
|
||||||
|
StpUtil.login(
|
||||||
|
userId,
|
||||||
|
SaLoginConfig.setExtra("url", loginUrl)
|
||||||
|
.setExtra("prv", prv)
|
||||||
|
.setExtra(
|
||||||
|
"exp",
|
||||||
|
String.valueOf(
|
||||||
|
System.currentTimeMillis()
|
||||||
|
+ authConfig.getExpired() * 1000L)));
|
||||||
|
return StpUtil.getTokenValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean check(String prv) {
|
||||||
|
if (!StpUtil.isLogin()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String tokenPrv = (String) StpUtil.getExtra("prv");
|
||||||
|
return prv.equals(tokenPrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer userId() {
|
||||||
|
return StpUtil.getLoginIdAsInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logout() {
|
||||||
|
StpUtil.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String jti() {
|
||||||
|
return (String) StpUtil.getExtra("rnStr");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long expired() {
|
||||||
|
return (Long) StpUtil.getExtra("exp");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<String, String> parse(String token) {
|
||||||
|
HashMap<String, String> data = new HashMap<>();
|
||||||
|
data.put("jti", (String) StpUtil.getExtra(token, "rnStr"));
|
||||||
|
data.put("exp", (String) StpUtil.getExtra(token, "exp"));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 杭州白书科技有限公司
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package xyz.playedu.api.service.impl;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import xyz.playedu.api.constant.SystemConstant;
|
||||||
|
import xyz.playedu.api.service.AuthService;
|
||||||
|
import xyz.playedu.api.service.BackendAuthService;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class BackendAuthServiceImpl implements BackendAuthService {
|
||||||
|
@Autowired private AuthService authService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String loginUsingId(Integer userId, String loginUrl) {
|
||||||
|
return authService.loginUsingId(userId, loginUrl, SystemConstant.JWT_PRV_ADMIN_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean check() {
|
||||||
|
return authService.check(SystemConstant.JWT_PRV_ADMIN_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer userId() {
|
||||||
|
return authService.userId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logout() {
|
||||||
|
authService.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String jti() {
|
||||||
|
return authService.jti();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<String, String> parse(String token) {
|
||||||
|
return authService.parse(token);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 杭州白书科技有限公司
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package xyz.playedu.api.service.impl;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import xyz.playedu.api.constant.SystemConstant;
|
||||||
|
import xyz.playedu.api.service.AuthService;
|
||||||
|
import xyz.playedu.api.service.FrontendAuthService;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class FrontendAuthServiceImpl implements FrontendAuthService {
|
||||||
|
|
||||||
|
@Autowired private AuthService authService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String loginUsingId(Integer userId, String loginUrl) {
|
||||||
|
return authService.loginUsingId(userId, loginUrl, SystemConstant.JWT_PRV_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean check() {
|
||||||
|
return authService.check(SystemConstant.JWT_PRV_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer userId() {
|
||||||
|
return authService.userId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logout() {
|
||||||
|
authService.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String jti() {
|
||||||
|
return authService.jti();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashMap<String, String> parse(String token) {
|
||||||
|
return authService.parse(token);
|
||||||
|
}
|
||||||
|
}
|
@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 杭州白书科技有限公司
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package xyz.playedu.api.service.impl;
|
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
|
||||||
import io.jsonwebtoken.JwtBuilder;
|
|
||||||
import io.jsonwebtoken.Jwts;
|
|
||||||
import io.jsonwebtoken.security.Keys;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import xyz.playedu.api.constant.SystemConstant;
|
|
||||||
import xyz.playedu.api.exception.JwtLogoutException;
|
|
||||||
import xyz.playedu.api.service.JWTService;
|
|
||||||
import xyz.playedu.api.types.JWTPayload;
|
|
||||||
import xyz.playedu.api.types.JwtToken;
|
|
||||||
import xyz.playedu.api.util.HelperUtil;
|
|
||||||
import xyz.playedu.api.util.RedisUtil;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
public class JwtServiceImpl implements JWTService {
|
|
||||||
|
|
||||||
@Value("${playedu.jwt.key}")
|
|
||||||
private String ConfigKey;
|
|
||||||
|
|
||||||
@Value("${playedu.jwt.expire}")
|
|
||||||
private Long ConfigExpire;
|
|
||||||
|
|
||||||
@Value("${playedu.jwt.cache-black-prefix}")
|
|
||||||
private String ConfigCacheBlackPrefix;
|
|
||||||
|
|
||||||
public JwtToken generate(Integer userId, String iss, String prv) {
|
|
||||||
long curTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
JWTPayload payload = new JWTPayload();
|
|
||||||
payload.setPrv(prv);
|
|
||||||
payload.setIss(iss);
|
|
||||||
payload.setJti(HelperUtil.uuid());
|
|
||||||
payload.setNbf(curTime);
|
|
||||||
payload.setIat(curTime);
|
|
||||||
payload.setExp(curTime + ConfigExpire * 1000);
|
|
||||||
payload.setSub(userId);
|
|
||||||
|
|
||||||
JwtBuilder builder = Jwts.builder();
|
|
||||||
builder.setId(payload.getJti())
|
|
||||||
.setIssuedAt(new Date(payload.getIat()))
|
|
||||||
.claim("prv", payload.getPrv());
|
|
||||||
builder.setExpiration(new Date(payload.getExp())).setIssuer(payload.getIss());
|
|
||||||
builder.setSubject(String.valueOf(payload.getSub()))
|
|
||||||
.setNotBefore(new Date(payload.getNbf()));
|
|
||||||
builder.signWith(getSecretKey());
|
|
||||||
|
|
||||||
JwtToken token = new JwtToken();
|
|
||||||
token.setToken(builder.compact());
|
|
||||||
token.setExpire(payload.getExp() / 1000);
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JWTPayload parse(String token, String prv) throws JwtLogoutException {
|
|
||||||
Claims claims = parseToken(token, prv);
|
|
||||||
JWTPayload payload = new JWTPayload();
|
|
||||||
|
|
||||||
payload.setSub(Integer.valueOf(claims.getSubject()));
|
|
||||||
payload.setIss(claims.getIssuer());
|
|
||||||
payload.setPrv((String) claims.get("prv"));
|
|
||||||
payload.setNbf(claims.getNotBefore().getTime());
|
|
||||||
payload.setExp(claims.getExpiration().getTime());
|
|
||||||
payload.setIat(claims.getIssuedAt().getTime());
|
|
||||||
payload.setJti(claims.getId());
|
|
||||||
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInBlack(String jti) {
|
|
||||||
return RedisUtil.exists(getBlackCacheKey(jti));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void logout(String token, String prv) throws JwtLogoutException {
|
|
||||||
Claims claims = parseToken(token, prv);
|
|
||||||
String cacheKey = getBlackCacheKey(claims.getId());
|
|
||||||
Long expire = (claims.getExpiration().getTime() - System.currentTimeMillis()) / 1000;
|
|
||||||
RedisUtil.set(cacheKey, 1, expire);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void userLogout(String token) throws JwtLogoutException {
|
|
||||||
logout(token, SystemConstant.JWT_PRV_USER);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void adminUserLogout(String token) throws JwtLogoutException {
|
|
||||||
logout(token, SystemConstant.JWT_PRV_ADMIN_USER);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Claims parseToken(String token, String prv) throws JwtLogoutException {
|
|
||||||
Claims claims =
|
|
||||||
(Claims)
|
|
||||||
Jwts.parserBuilder()
|
|
||||||
.setSigningKey(getSecretKey())
|
|
||||||
.require("prv", prv)
|
|
||||||
.build()
|
|
||||||
.parse(token)
|
|
||||||
.getBody();
|
|
||||||
if (isInBlack(claims.getId())) {
|
|
||||||
throw new JwtLogoutException();
|
|
||||||
}
|
|
||||||
return claims;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SecretKey getSecretKey() {
|
|
||||||
return Keys.hmacShaKeyFor(ConfigKey.getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getBlackCacheKey(String jti) {
|
|
||||||
return ConfigCacheBlackPrefix + jti;
|
|
||||||
}
|
|
||||||
}
|
|
@ -56,6 +56,14 @@ mybatis-plus:
|
|||||||
# configuration:
|
# configuration:
|
||||||
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||||
|
|
||||||
|
sa-token:
|
||||||
|
token-name: "Authorization"
|
||||||
|
timeout: 1296000 #token有效期[单位:秒,默认15天]
|
||||||
|
is-concurrent: false #限制同时登录
|
||||||
|
is-share: false
|
||||||
|
jwt-secret-key: "playeduxyz"
|
||||||
|
token-prefix: "Bearer"
|
||||||
|
|
||||||
# PlayEdu
|
# PlayEdu
|
||||||
playedu:
|
playedu:
|
||||||
# 图形验证码
|
# 图形验证码
|
||||||
|
Loading…
x
Reference in New Issue
Block a user