mirror of
https://github.com/201206030/novel.git
synced 2025-04-27 07:30:50 +00:00
refactor: 策略模式重构用户认证授权功能
This commit is contained in:
parent
cdd1455ab9
commit
d2e7590646
@ -0,0 +1,27 @@
|
||||
package io.github.xxyopen.novel.core.auth;
|
||||
|
||||
import io.github.xxyopen.novel.core.common.exception.BusinessException;
|
||||
import io.github.xxyopen.novel.core.util.JwtUtils;
|
||||
import io.github.xxyopen.novel.dao.mapper.UserInfoMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 平台后台管理系统 认证策略
|
||||
*
|
||||
* @author xiongxiaoyang
|
||||
* @date 2022/5/18
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AdminAuthStrategy implements AuthStrategy {
|
||||
|
||||
private final JwtUtils jwtUtils;
|
||||
|
||||
private final UserInfoMapper userInfoMapper;
|
||||
|
||||
@Override
|
||||
public void auth(String token) throws BusinessException {
|
||||
// TODO 平台后台 token 校验
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package io.github.xxyopen.novel.core.auth;
|
||||
|
||||
import io.github.xxyopen.novel.core.common.constant.ErrorCodeEnum;
|
||||
import io.github.xxyopen.novel.core.common.exception.BusinessException;
|
||||
import io.github.xxyopen.novel.core.constant.SystemConfigConsts;
|
||||
import io.github.xxyopen.novel.core.util.JwtUtils;
|
||||
import io.github.xxyopen.novel.dao.entity.UserInfo;
|
||||
import io.github.xxyopen.novel.dao.mapper.UserInfoMapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 策略模式实现用户认证授权功能
|
||||
*
|
||||
* @author xiongxiaoyang
|
||||
* @date 2022/5/18
|
||||
*/
|
||||
public interface AuthStrategy {
|
||||
|
||||
/**
|
||||
* 请求用户认证
|
||||
*
|
||||
* @param token 登录 token
|
||||
* @throws BusinessException 认证失败则抛出义务异常
|
||||
*/
|
||||
void auth(String token) throws BusinessException;
|
||||
|
||||
/**
|
||||
* 前台多系统单点登录统一账号认证(门户系统、作家系统以及后面会扩展的漫画系统和视频系统等)
|
||||
*
|
||||
* @param jwtUtils jwt 工具
|
||||
* @param userInfoMapper 用户查询 Mapper
|
||||
* @param token token 登录 token
|
||||
* @return 用户ID
|
||||
*/
|
||||
default Long authSSO(JwtUtils jwtUtils, UserInfoMapper userInfoMapper, String token) {
|
||||
if (Objects.isNull(token)) {
|
||||
// token 为空
|
||||
throw new BusinessException(ErrorCodeEnum.USER_LOGIN_EXPIRED);
|
||||
}
|
||||
Long userId = jwtUtils.parseToken(token, SystemConfigConsts.NOVEL_FRONT_KEY);
|
||||
if (Objects.isNull(userId)) {
|
||||
// token 解析失败
|
||||
throw new BusinessException(ErrorCodeEnum.USER_LOGIN_EXPIRED);
|
||||
}
|
||||
UserInfo userInfo = userInfoMapper.selectById(userId);
|
||||
if (Objects.isNull(userInfo)) {
|
||||
// 用户不存在
|
||||
throw new BusinessException(ErrorCodeEnum.USER_ACCOUNT_NOT_EXIST);
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package io.github.xxyopen.novel.core.auth;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import io.github.xxyopen.novel.core.common.constant.ErrorCodeEnum;
|
||||
import io.github.xxyopen.novel.core.common.exception.BusinessException;
|
||||
import io.github.xxyopen.novel.core.constant.DatabaseConsts;
|
||||
import io.github.xxyopen.novel.core.util.JwtUtils;
|
||||
import io.github.xxyopen.novel.dao.entity.AuthorInfo;
|
||||
import io.github.xxyopen.novel.dao.mapper.AuthorInfoMapper;
|
||||
import io.github.xxyopen.novel.dao.mapper.UserInfoMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 作家后台管理系统 认证策略
|
||||
*
|
||||
* @author xiongxiaoyang
|
||||
* @date 2022/5/18
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class AuthorAuthStrategy implements AuthStrategy {
|
||||
|
||||
private final JwtUtils jwtUtils;
|
||||
|
||||
private final UserInfoMapper userInfoMapper;
|
||||
|
||||
private final AuthorInfoMapper authorInfoMapper;
|
||||
|
||||
@Override
|
||||
public void auth(String token) throws BusinessException {
|
||||
// 统一账号认证
|
||||
Long userId = authSSO(jwtUtils, userInfoMapper, token);
|
||||
|
||||
// 作家权限认证
|
||||
QueryWrapper<AuthorInfo> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper
|
||||
.eq(DatabaseConsts.AuthorInfoTable.ColumnEnum.USER_ID.getName(), userId)
|
||||
.last(DatabaseConsts.SqlEnum.LIMIT_1.getSql());
|
||||
AuthorInfo authorInfo = authorInfoMapper.selectOne(queryWrapper);
|
||||
if(Objects.isNull(authorInfo)){
|
||||
// 作家账号不存在,无权访问作家专区
|
||||
throw new BusinessException(ErrorCodeEnum.USER_UN_AUTH);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package io.github.xxyopen.novel.core.auth;
|
||||
|
||||
import io.github.xxyopen.novel.core.common.exception.BusinessException;
|
||||
import io.github.xxyopen.novel.core.util.JwtUtils;
|
||||
import io.github.xxyopen.novel.dao.mapper.UserInfoMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 前台门户系统 认证策略
|
||||
*
|
||||
* @author xiongxiaoyang
|
||||
* @date 2022/5/18
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class FrontAuthStrategy implements AuthStrategy {
|
||||
|
||||
private final JwtUtils jwtUtils;
|
||||
|
||||
private final UserInfoMapper userInfoMapper;
|
||||
|
||||
@Override
|
||||
public void auth(String token) throws BusinessException {
|
||||
// 统一账号认证
|
||||
authSSO(jwtUtils,userInfoMapper,token);
|
||||
}
|
||||
}
|
@ -77,6 +77,11 @@ public enum ErrorCodeEnum {
|
||||
* */
|
||||
USER_LOGIN_EXPIRED("A0230","用户登录已过期"),
|
||||
|
||||
/**
|
||||
* 访问未授权
|
||||
* */
|
||||
USER_UN_AUTH("A0301","访问未授权"),
|
||||
|
||||
/**
|
||||
* 一级宏观错误码,系统执行出错
|
||||
* */
|
||||
|
@ -32,7 +32,8 @@ public class WebConfig implements WebMvcConfigurer {
|
||||
, ApiRouterConsts.API_ADMIN_URL_PREFIX + "/**")
|
||||
// 放行登录注册相关请求接口
|
||||
.excludePathPatterns(ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/register"
|
||||
, ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/login",
|
||||
ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login");
|
||||
, ApiRouterConsts.API_FRONT_USER_URL_PREFIX + "/login"
|
||||
, ApiRouterConsts.API_AUTHOR_URL_PREFIX + "/register"
|
||||
,ApiRouterConsts.API_ADMIN_URL_PREFIX + "/login");
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,26 @@ public class DatabaseConsts {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 作家信息表
|
||||
*/
|
||||
public static class AuthorInfoTable {
|
||||
|
||||
@Getter
|
||||
public enum ColumnEnum {
|
||||
|
||||
USER_ID("user_id");
|
||||
|
||||
private String name;
|
||||
|
||||
ColumnEnum(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 小说类别表
|
||||
*/
|
||||
|
@ -1,11 +1,12 @@
|
||||
package io.github.xxyopen.novel.core.intercepter;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.github.xxyopen.novel.core.auth.AuthStrategy;
|
||||
import io.github.xxyopen.novel.core.common.constant.ErrorCodeEnum;
|
||||
import io.github.xxyopen.novel.core.common.exception.BusinessException;
|
||||
import io.github.xxyopen.novel.core.common.resp.RestResp;
|
||||
import io.github.xxyopen.novel.core.constant.ApiRouterConsts;
|
||||
import io.github.xxyopen.novel.core.constant.SystemConfigConsts;
|
||||
import io.github.xxyopen.novel.core.util.JwtUtils;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -14,7 +15,7 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 认证 拦截器
|
||||
@ -27,34 +28,36 @@ import java.util.Objects;
|
||||
@RequiredArgsConstructor
|
||||
public class AuthInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final JwtUtils jwtUtils;
|
||||
private final Map<String,AuthStrategy> authStrategy;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
// 校验登录JWT
|
||||
// 获取登录 JWT
|
||||
String token = request.getHeader(SystemConfigConsts.HTTP_AUTH_HEADER_NAME);
|
||||
if (!Objects.isNull(token)) {
|
||||
String requestUri = request.getRequestURI();
|
||||
if (requestUri.contains(ApiRouterConsts.API_FRONT_USER_URL_PREFIX)
|
||||
|| requestUri.contains(ApiRouterConsts.API_AUTHOR_URL_PREFIX)) {
|
||||
// 校验会员和作家的登录权限
|
||||
Long userId = jwtUtils.parseToken(token, SystemConfigConsts.NOVEL_FRONT_KEY);
|
||||
if (!Objects.isNull(userId)) {
|
||||
// TODO 查询用户信息并校验账号状态是否正常
|
||||
// 认证成功
|
||||
return HandlerInterceptor.super.preHandle(request, response, handler);
|
||||
}
|
||||
}else{
|
||||
// TODO 校验后台的登录权限
|
||||
}
|
||||
|
||||
}
|
||||
// 获取请求的 URI
|
||||
String requestUri = request.getRequestURI();
|
||||
|
||||
// 根据请求的 URI 得到认证策略
|
||||
String authStrategyName = requestUri.substring(ApiRouterConsts.API_URL_PREFIX.length() + 1);
|
||||
authStrategyName = authStrategyName.substring(0,authStrategyName.indexOf("/"));
|
||||
authStrategyName = String.format("%sAuthStrategy",authStrategyName);
|
||||
|
||||
// 开始认证
|
||||
try {
|
||||
authStrategy.get(authStrategyName).auth(token);
|
||||
}catch (BusinessException exception){
|
||||
// 认证失败
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getWriter().write(objectMapper.writeValueAsString(RestResp.fail(ErrorCodeEnum.USER_LOGIN_EXPIRED)));
|
||||
return false;
|
||||
}
|
||||
// 认证成功
|
||||
return HandlerInterceptor.super.preHandle(request, response, handler);
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user