diff --git a/pom.xml b/pom.xml
index 61e8723..4109ed8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -138,6 +138,25 @@
5.8.16
+
+
+ cn.dev33
+ sa-token-spring-boot3-starter
+ 1.34.0
+
+
+
+ cn.dev33
+ sa-token-dao-redis-jackson
+ 1.34.0
+
+
+
+ cn.dev33
+ sa-token-jwt
+ 1.34.0
+
+
org.springdoc
springdoc-openapi-starter-webmvc-ui
diff --git a/src/main/java/xyz/playedu/api/FCtx.java b/src/main/java/xyz/playedu/api/FCtx.java
index 4b6ebb1..56ae4d3 100644
--- a/src/main/java/xyz/playedu/api/FCtx.java
+++ b/src/main/java/xyz/playedu/api/FCtx.java
@@ -19,11 +19,6 @@ import xyz.playedu.api.domain.User;
import java.util.LinkedHashMap;
-/**
- * @Author 杭州白书科技有限公司
- *
- * @create 2023/3/13 09:24
- */
public class FCtx {
private static final java.lang.ThreadLocal> THREAD_LOCAL =
new java.lang.ThreadLocal<>();
diff --git a/src/main/java/xyz/playedu/api/types/JwtToken.java b/src/main/java/xyz/playedu/api/config/AuthConfig.java
similarity index 71%
rename from src/main/java/xyz/playedu/api/types/JwtToken.java
rename to src/main/java/xyz/playedu/api/config/AuthConfig.java
index 5c1ca87..d793b75 100644
--- a/src/main/java/xyz/playedu/api/types/JwtToken.java
+++ b/src/main/java/xyz/playedu/api/config/AuthConfig.java
@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package xyz.playedu.api.types;
+package xyz.playedu.api.config;
import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
@Data
-public class JwtToken {
-
- private String token;
-
- private Long expire;
+public class AuthConfig {
+ @Value("${sa-token.timeout}")
+ private Integer expired;
}
diff --git a/src/main/java/xyz/playedu/api/config/SaTokenConfigure.java b/src/main/java/xyz/playedu/api/config/SaTokenConfigure.java
new file mode 100644
index 0000000..02c8ec2
--- /dev/null
+++ b/src/main/java/xyz/playedu/api/config/SaTokenConfigure.java
@@ -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();
+ }
+}
diff --git a/src/main/java/xyz/playedu/api/controller/ExceptionController.java b/src/main/java/xyz/playedu/api/controller/ExceptionController.java
index 5bc268b..6358dd2 100644
--- a/src/main/java/xyz/playedu/api/controller/ExceptionController.java
+++ b/src/main/java/xyz/playedu/api/controller/ExceptionController.java
@@ -37,11 +37,11 @@ import java.util.List;
@Slf4j
public class ExceptionController {
- @ExceptionHandler(Exception.class)
- public JsonResponse exceptionHandler(Exception e) {
- log.error(e.getMessage());
- return JsonResponse.error("系统错误", 500);
- }
+ // @ExceptionHandler(Exception.class)
+ // public JsonResponse exceptionHandler(Exception e) {
+ // log.error(e.getMessage());
+ // return JsonResponse.error("系统错误", 500);
+ // }
@ExceptionHandler(ServiceException.class)
public JsonResponse serviceExceptionHandler(ServiceException e) {
diff --git a/src/main/java/xyz/playedu/api/controller/backend/LoginController.java b/src/main/java/xyz/playedu/api/controller/backend/LoginController.java
index 119b177..bb42749 100644
--- a/src/main/java/xyz/playedu/api/controller/backend/LoginController.java
+++ b/src/main/java/xyz/playedu/api/controller/backend/LoginController.java
@@ -23,7 +23,6 @@ import org.springframework.web.bind.annotation.*;
import xyz.playedu.api.BCtx;
import xyz.playedu.api.bus.BackendBus;
import xyz.playedu.api.constant.BPermissionConstant;
-import xyz.playedu.api.constant.SystemConstant;
import xyz.playedu.api.domain.AdminUser;
import xyz.playedu.api.event.AdminUserLoginEvent;
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.PasswordChangeRequest;
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.JwtToken;
import xyz.playedu.api.util.HelperUtil;
import xyz.playedu.api.util.IpUtil;
import xyz.playedu.api.util.RequestUtil;
@@ -49,7 +47,7 @@ public class LoginController {
@Autowired private BackendBus backendBus;
- @Autowired private JWTService jwtService;
+ @Autowired private BackendAuthService authService;
@Autowired private ApplicationContext ctx;
@@ -69,19 +67,16 @@ public class LoginController {
return JsonResponse.error("当前用户已禁止登录");
}
- String url = RequestUtil.url();
- JwtToken token =
- jwtService.generate(adminUser.getId(), url, SystemConstant.JWT_PRV_ADMIN_USER);
+ String token = authService.loginUsingId(adminUser.getId(), RequestUtil.url());
HashMap data = new HashMap<>();
- data.put("token", token.getToken());
- data.put("expire", token.getExpire());
+ data.put("token", token);
ctx.publishEvent(
new AdminUserLoginEvent(
this,
adminUser.getId(),
- token.getToken(),
+ token,
IpUtil.getIpAddress(),
adminUser.getLoginTimes()));
@@ -90,7 +85,7 @@ public class LoginController {
@PostMapping("/logout")
public JsonResponse logout() throws JwtLogoutException {
- jwtService.adminUserLogout(RequestUtil.token());
+ authService.logout();
return JsonResponse.success("success");
}
diff --git a/src/main/java/xyz/playedu/api/controller/frontend/LoginController.java b/src/main/java/xyz/playedu/api/controller/frontend/LoginController.java
index b5ad7ea..b33f2d1 100644
--- a/src/main/java/xyz/playedu/api/controller/frontend/LoginController.java
+++ b/src/main/java/xyz/playedu/api/controller/frontend/LoginController.java
@@ -24,36 +24,28 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xyz.playedu.api.FCtx;
-import xyz.playedu.api.constant.SystemConstant;
import xyz.playedu.api.domain.User;
import xyz.playedu.api.event.UserLoginEvent;
import xyz.playedu.api.event.UserLogoutEvent;
-import xyz.playedu.api.exception.JwtLogoutException;
import xyz.playedu.api.exception.LimitException;
import xyz.playedu.api.middleware.ImageCaptchaCheckMiddleware;
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.types.JsonResponse;
-import xyz.playedu.api.types.JwtToken;
import xyz.playedu.api.util.HelperUtil;
import xyz.playedu.api.util.IpUtil;
import xyz.playedu.api.util.RequestUtil;
import java.util.HashMap;
-/**
- * @Author 杭州白书科技有限公司
- *
- * @create 2023/3/2 21:51
- */
@RestController
@RequestMapping("/api/v1/auth/login")
public class LoginController {
@Autowired private UserService userService;
- @Autowired private JWTService jwtService;
+ @Autowired private FrontendAuthService authService;
@Autowired private ApplicationContext ctx;
@@ -74,19 +66,17 @@ public class LoginController {
return JsonResponse.error("当前学员已锁定无法登录");
}
- JwtToken token =
- jwtService.generate(user.getId(), RequestUtil.url(), SystemConstant.JWT_PRV_USER);
+ String token = authService.loginUsingId(user.getId(), RequestUtil.url());
HashMap data = new HashMap<>();
- data.put("token", token.getToken());
- data.put("expired", token.getExpire());
+ data.put("token", token);
ctx.publishEvent(
new UserLoginEvent(
this,
user.getId(),
user.getEmail(),
- token.getToken(),
+ token,
IpUtil.getIpAddress(),
RequestUtil.ua()));
@@ -94,8 +84,8 @@ public class LoginController {
}
@PostMapping("/logout")
- public JsonResponse logout() throws JwtLogoutException {
- jwtService.userLogout(RequestUtil.token());
+ public JsonResponse logout() {
+ authService.logout();
ctx.publishEvent(new UserLogoutEvent(this, FCtx.getId(), FCtx.getJwtJti()));
return JsonResponse.success();
}
diff --git a/src/main/java/xyz/playedu/api/controller/frontend/UserController.java b/src/main/java/xyz/playedu/api/controller/frontend/UserController.java
index 00c5876..9091b97 100644
--- a/src/main/java/xyz/playedu/api/controller/frontend/UserController.java
+++ b/src/main/java/xyz/playedu/api/controller/frontend/UserController.java
@@ -66,8 +66,11 @@ public class UserController {
@GetMapping("/detail")
public JsonResponse detail() {
User user = FCtx.getUser();
- List departments =
- departmentService.listByIds(userService.getDepIdsByUserId(user.getId()));
+ List departments = new ArrayList<>();
+ List depIds = userService.getDepIdsByUserId(user.getId());
+ if (depIds != null && depIds.size() > 0) {
+ departmentService.listByIds(depIds);
+ }
user.setIdCard(PrivacyUtil.hideIDCard(user.getIdCard()));
diff --git a/src/main/java/xyz/playedu/api/listener/UserLoginListener.java b/src/main/java/xyz/playedu/api/listener/UserLoginListener.java
index 7eb0823..fdfce20 100644
--- a/src/main/java/xyz/playedu/api/listener/UserLoginListener.java
+++ b/src/main/java/xyz/playedu/api/listener/UserLoginListener.java
@@ -22,36 +22,34 @@ import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
-import xyz.playedu.api.constant.SystemConstant;
import xyz.playedu.api.event.UserLoginEvent;
-import xyz.playedu.api.exception.JwtLogoutException;
-import xyz.playedu.api.service.JWTService;
+import xyz.playedu.api.service.FrontendAuthService;
import xyz.playedu.api.service.UserLoginRecordService;
-import xyz.playedu.api.types.JWTPayload;
import xyz.playedu.api.util.IpUtil;
-/**
- * @Author 杭州白书科技有限公司
- *
- * @create 2023/3/10 13:45
- */
+import java.util.HashMap;
+
@Component
@Slf4j
public class UserLoginListener {
@Autowired private UserLoginRecordService loginRecordService;
- @Autowired private JWTService jwtService;
+ @Autowired private FrontendAuthService authService;
@Async
@EventListener
- public void updateLoginInfo(UserLoginEvent event) throws JwtLogoutException {
+ public void updateLoginInfo(UserLoginEvent event) {
String ipArea = IpUtil.getRealAddressByIP(event.getIp());
- JWTPayload payload = jwtService.parse(event.getToken(), SystemConstant.JWT_PRV_USER);
+
+ HashMap tokenData = authService.parse(event.getToken());
+ String jti = tokenData.get("jti");
+ Long exp = Long.parseLong(tokenData.get("exp"));
+
loginRecordService.store(
event.getUserId(),
- payload.getJti(),
- payload.getExp(),
+ jti,
+ exp,
event.getIp(),
ipArea,
event.getUserAgent().getBrowser().toString(),
diff --git a/src/main/java/xyz/playedu/api/middleware/AdminMiddleware.java b/src/main/java/xyz/playedu/api/middleware/AdminMiddleware.java
index f7f9e3e..298e30a 100644
--- a/src/main/java/xyz/playedu/api/middleware/AdminMiddleware.java
+++ b/src/main/java/xyz/playedu/api/middleware/AdminMiddleware.java
@@ -27,15 +27,12 @@ import org.springframework.web.servlet.HandlerInterceptor;
import xyz.playedu.api.BCtx;
import xyz.playedu.api.bus.AppBus;
import xyz.playedu.api.bus.BackendBus;
-import xyz.playedu.api.constant.SystemConstant;
import xyz.playedu.api.domain.AdminUser;
import xyz.playedu.api.service.AdminUserService;
import xyz.playedu.api.service.AppConfigService;
-import xyz.playedu.api.service.JWTService;
-import xyz.playedu.api.types.JWTPayload;
+import xyz.playedu.api.service.BackendAuthService;
import xyz.playedu.api.types.JsonResponse;
import xyz.playedu.api.util.HelperUtil;
-import xyz.playedu.api.util.RequestUtil;
import java.io.IOException;
import java.util.Map;
@@ -44,7 +41,7 @@ import java.util.Map;
@Slf4j
public class AdminMiddleware implements HandlerInterceptor {
- @Autowired private JWTService jwtService;
+ @Autowired private BackendAuthService authService;
@Autowired private AdminUserService adminUserService;
@@ -70,33 +67,23 @@ public class AdminMiddleware implements HandlerInterceptor {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
- String token = RequestUtil.token();
- if (token.length() == 0) {
+ if (!authService.check()) {
return responseTransform(response, 401, "请登录");
}
- try {
- JWTPayload payload = jwtService.parse(token, SystemConstant.JWT_PRV_ADMIN_USER);
-
- AdminUser adminUser = adminUserService.findById(payload.getSub());
- if (adminUser == null) {
- return responseTransform(response, 401, "管理员不存在");
- }
- if (adminUser.getIsBanLogin() == 1) {
- return responseTransform(response, 403, "当前管理员禁止登录");
- }
-
- BCtx.setId(payload.getSub());
- BCtx.setAdminUser(adminUser);
- BCtx.setAdminPer(backendBus.adminUserPermissions(adminUser.getId()));
-
- return HandlerInterceptor.super.preHandle(request, response, handler);
- } catch (Exception e) {
- if (appBus.isDev()) {
- log.debug("jwt解析失败:" + e.getMessage());
- }
- return responseTransform(response, 401, "请重新登录");
+ AdminUser adminUser = adminUserService.findById(authService.userId());
+ if (adminUser == null) {
+ return responseTransform(response, 401, "管理员不存在");
}
+ if (adminUser.getIsBanLogin() == 1) {
+ return responseTransform(response, 403, "当前管理员禁止登录");
+ }
+
+ BCtx.setId(authService.userId());
+ BCtx.setAdminUser(adminUser);
+ BCtx.setAdminPer(backendBus.adminUserPermissions(adminUser.getId()));
+
+ return HandlerInterceptor.super.preHandle(request, response, handler);
}
private boolean responseTransform(HttpServletResponse response, int code, String msg)
diff --git a/src/main/java/xyz/playedu/api/middleware/FrontMiddleware.java b/src/main/java/xyz/playedu/api/middleware/FrontMiddleware.java
index 8b6248f..2ad5da5 100644
--- a/src/main/java/xyz/playedu/api/middleware/FrontMiddleware.java
+++ b/src/main/java/xyz/playedu/api/middleware/FrontMiddleware.java
@@ -26,27 +26,19 @@ import org.springframework.web.servlet.HandlerInterceptor;
import xyz.playedu.api.FCtx;
import xyz.playedu.api.constant.FrontendConstant;
-import xyz.playedu.api.constant.SystemConstant;
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.types.JWTPayload;
import xyz.playedu.api.types.JsonResponse;
import xyz.playedu.api.util.HelperUtil;
-import xyz.playedu.api.util.RequestUtil;
import java.io.IOException;
-/**
- * @Author 杭州白书科技有限公司
- *
- * @create 2023/3/13 09:40
- */
@Component
@Slf4j
public class FrontMiddleware implements HandlerInterceptor {
- @Autowired private JWTService jwtService;
+ @Autowired private FrontendAuthService authService;
@Autowired private UserService userService;
@@ -62,31 +54,23 @@ public class FrontMiddleware implements HandlerInterceptor {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
- String token = RequestUtil.token();
- if (token.length() == 0) {
+ if (!authService.check()) {
return responseTransform(response, 401, "请登录");
}
- try {
- JWTPayload payload = jwtService.parse(token, SystemConstant.JWT_PRV_USER);
-
- User user = userService.find(payload.getSub());
- if (user == null) {
- return responseTransform(response, 401, "请重新登录");
- }
- if (user.getIsLock() == 1) {
- return responseTransform(response, 403, "当前学员已锁定无法登录");
- }
-
- FCtx.setUser(user);
- FCtx.setId(user.getId());
- FCtx.setJWtJti(payload.getJti());
-
- return HandlerInterceptor.super.preHandle(request, response, handler);
- } catch (Exception e) {
- log.error(e.getMessage());
+ User user = userService.find(authService.userId());
+ if (user == null) {
return responseTransform(response, 401, "请重新登录");
}
+ if (user.getIsLock() == 1) {
+ return responseTransform(response, 403, "当前学员已锁定无法登录");
+ }
+
+ FCtx.setUser(user);
+ FCtx.setId(user.getId());
+ FCtx.setJWtJti(authService.jti());
+
+ return HandlerInterceptor.super.preHandle(request, response, handler);
}
private boolean responseTransform(HttpServletResponse response, int code, String msg)
diff --git a/src/main/java/xyz/playedu/api/types/JWTPayload.java b/src/main/java/xyz/playedu/api/service/AuthService.java
similarity index 57%
rename from src/main/java/xyz/playedu/api/types/JWTPayload.java
rename to src/main/java/xyz/playedu/api/service/AuthService.java
index 4b8f262..385bf67 100644
--- a/src/main/java/xyz/playedu/api/types/JWTPayload.java
+++ b/src/main/java/xyz/playedu/api/service/AuthService.java
@@ -13,34 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package xyz.playedu.api.types;
+package xyz.playedu.api.service;
-import lombok.Data;
+import java.util.HashMap;
-/**
- * @see https://www.rfc-editor.org/rfc/rfc7519#section-4.1
- */
-@Data
-public class JWTPayload {
+public interface AuthService {
+ String loginUsingId(Integer userId, String loginUrl, String prv);
- /** subject */
- private Integer sub;
+ boolean check(String prv);
- /** Issued At */
- private Long iat;
+ Integer userId();
- /** Expiration Time */
- private Long exp;
+ void logout();
- /** Not Before */
- private Long nbf;
+ String jti();
- /** JWT ID */
- private String jti;
+ Long expired();
- /** Issuer */
- private String iss;
-
- /** Payload */
- private String prv;
+ HashMap parse(String token);
}
diff --git a/src/main/java/xyz/playedu/api/service/JWTService.java b/src/main/java/xyz/playedu/api/service/BackendAuthService.java
similarity index 55%
rename from src/main/java/xyz/playedu/api/service/JWTService.java
rename to src/main/java/xyz/playedu/api/service/BackendAuthService.java
index 5290732..2d1c5f6 100644
--- a/src/main/java/xyz/playedu/api/service/JWTService.java
+++ b/src/main/java/xyz/playedu/api/service/BackendAuthService.java
@@ -15,20 +15,18 @@
*/
package xyz.playedu.api.service;
-import xyz.playedu.api.exception.JwtLogoutException;
-import xyz.playedu.api.types.JWTPayload;
-import xyz.playedu.api.types.JwtToken;
+import java.util.HashMap;
-public interface JWTService {
- JwtToken generate(Integer userId, String iss, String prv);
+public interface BackendAuthService {
+ 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 parse(String token);
}
diff --git a/src/main/java/xyz/playedu/api/service/FrontendAuthService.java b/src/main/java/xyz/playedu/api/service/FrontendAuthService.java
new file mode 100644
index 0000000..b9d641a
--- /dev/null
+++ b/src/main/java/xyz/playedu/api/service/FrontendAuthService.java
@@ -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 parse(String token);
+}
diff --git a/src/main/java/xyz/playedu/api/service/UserLoginRecordService.java b/src/main/java/xyz/playedu/api/service/UserLoginRecordService.java
index 0b94bfd..01ef9be 100644
--- a/src/main/java/xyz/playedu/api/service/UserLoginRecordService.java
+++ b/src/main/java/xyz/playedu/api/service/UserLoginRecordService.java
@@ -19,11 +19,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
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 store(
Integer userId,
diff --git a/src/main/java/xyz/playedu/api/service/impl/AuthServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/AuthServiceImpl.java
new file mode 100644
index 0000000..cb32e54
--- /dev/null
+++ b/src/main/java/xyz/playedu/api/service/impl/AuthServiceImpl.java
@@ -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 parse(String token) {
+ HashMap data = new HashMap<>();
+ data.put("jti", (String) StpUtil.getExtra(token, "rnStr"));
+ data.put("exp", (String) StpUtil.getExtra(token, "exp"));
+ return data;
+ }
+}
diff --git a/src/main/java/xyz/playedu/api/service/impl/BackendAuthServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/BackendAuthServiceImpl.java
new file mode 100644
index 0000000..62e569c
--- /dev/null
+++ b/src/main/java/xyz/playedu/api/service/impl/BackendAuthServiceImpl.java
@@ -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 parse(String token) {
+ return authService.parse(token);
+ }
+}
diff --git a/src/main/java/xyz/playedu/api/service/impl/FrontendAuthServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/FrontendAuthServiceImpl.java
new file mode 100644
index 0000000..ecc0743
--- /dev/null
+++ b/src/main/java/xyz/playedu/api/service/impl/FrontendAuthServiceImpl.java
@@ -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 parse(String token) {
+ return authService.parse(token);
+ }
+}
diff --git a/src/main/java/xyz/playedu/api/service/impl/JwtServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/JwtServiceImpl.java
deleted file mode 100644
index 2a6cf09..0000000
--- a/src/main/java/xyz/playedu/api/service/impl/JwtServiceImpl.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 2d059e9..1d5e3a2 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -56,6 +56,14 @@ mybatis-plus:
# configuration:
# 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:
# 图形验证码