接入sa-token

This commit is contained in:
none
2023-06-09 14:37:40 +08:00
parent 5005e76b81
commit c9371b0589
20 changed files with 388 additions and 295 deletions

View File

@@ -15,20 +15,20 @@
*/
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 AuthService {
String loginUsingId(Integer userId, String loginUrl, String prv);
boolean isInBlack(String jti);
boolean check(String prv);
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;
Long expired();
HashMap<String, String> parse(String token);
}

View File

@@ -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 BackendAuthService {
String loginUsingId(Integer userId, String loginUrl);
boolean check();
Integer userId();
void logout();
String jti();
HashMap<String, String> parse(String token);
}

View File

@@ -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);
}

View File

@@ -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> {
UserLoginRecord store(
Integer userId,

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}