feat: auth模块初始化

This commit is contained in:
2025-11-28 23:36:41 +08:00
parent 3f31f3739e
commit 26a587f20b
25 changed files with 251 additions and 77 deletions

View File

@ -16,6 +16,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool.v7</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

View File

@ -1,13 +1,11 @@
package day.gitlab.dolphin.common.core.exception;
import day.gitlab.dolphin.common.core.entity.Result;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Component
@ControllerAdvice
public class GlobalExceptionAdvice {
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = BusinessException.class)
public Result handleBusinessException(BusinessException e) {

View File

@ -40,6 +40,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
// 在未启用或是忽略校验的地址时直接放行
if (!securityConfig.isEnabled() || authorityIgnoreInitializer.isIgnoreUrl(request)) {
filterChain.doFilter(request, response);
return;
}
try {
@ -51,6 +52,11 @@ public class AuthenticationFilter extends OncePerRequestFilter {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
response.getWriter().write(new ObjectMapper().writeValueAsString(Result.failure(e)));
} catch (Exception e) {
response.setStatus(500);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
response.getWriter().write(new ObjectMapper().writeValueAsString(Result.failure(e.getMessage())));
} finally {
SecurityContextHolder.clearAuthentication();
}

View File

@ -2,6 +2,7 @@ package day.gitlab.dolphin.common.security.annotation;
import day.gitlab.dolphin.common.security.config.SecurityConfig;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
@ -21,6 +22,7 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Component
public class AuthorityIgnoreInitializer implements ApplicationContextAware {
@ -34,6 +36,8 @@ public class AuthorityIgnoreInitializer implements ApplicationContextAware {
RequestMappingHandlerMapping requestMappingHandlerMapping = ctx.getBean(RequestMappingHandlerMapping.class);
Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
log.info("authorityIgnoreInitialize begin, contextPath: {}", contextPath);
if (StringUtils.hasText(securityConfig.getIgnoreUrls())) {
Arrays.stream(securityConfig.getIgnoreUrls().split(","))
.filter(StringUtils::hasText)
@ -45,6 +49,7 @@ public class AuthorityIgnoreInitializer implements ApplicationContextAware {
.map(IgnoreUrl::new)
.forEach(this.ignoreUrls::add);
}
log.info("authorityIgnoreInitialize default urls: {}", this.ignoreUrls);
for (RequestMappingInfo mappingInfo : handlerMethods.keySet()) {
HandlerMethod handlerMethod = handlerMethods.get(mappingInfo);
@ -75,11 +80,19 @@ public class AuthorityIgnoreInitializer implements ApplicationContextAware {
urlPrefix.add(prefixUrl);
}
urlPrefix.stream()
List<IgnoreUrl> methodIgnoreUrls = urlPrefix.stream()
.flatMap(sub -> mappingInfo.getPatternValues().stream().filter(StringUtils::hasText).map(s -> sub + s))
.map(IgnoreUrl::new)
.forEach(this.ignoreUrls::add);
.toList();
log.info("authorityIgnoreInitialize class [{}] method [{}] urls: {}", beanClass.getCanonicalName(), handlerMethod.getMethod().getName(), methodIgnoreUrls);
if (!methodIgnoreUrls.isEmpty()) {
ignoreUrls.addAll(methodIgnoreUrls);
}
}
log.info("authorityIgnoreInitialize current urls: {}", this.ignoreUrls);
log.info("authorityIgnoreInitialize end");
}
public boolean isIgnoreUrl(HttpServletRequest request) {

View File

@ -1,5 +1,6 @@
package day.gitlab.dolphin.common.security.jwt;
import cn.hutool.v7.crypto.digest.DigestUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
@ -64,7 +65,7 @@ public class Jwt {
}
private SecretKey getSigningKey() {
byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
byte[] keyBytes = DigestUtil.sha256(secret);
return Keys.hmacShaKeyFor(keyBytes);
}
}

View File

@ -15,7 +15,7 @@
<!-- Project -->
<dependency>
<groupId>day.gitlab</groupId>
<artifactId>dolphin-common-security</artifactId>
<artifactId>dolphin-module-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
@ -23,6 +23,11 @@
<artifactId>dolphin-module-rbac</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>day.gitlab</groupId>
<artifactId>dolphin-module-auth</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
@ -52,6 +57,19 @@
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>

View File

@ -1,11 +0,0 @@
package day.gitlab.dolphin.authorize.entity.dto;
import lombok.Data;
@Data
public class LoginDTO {
private String username;
private String password;
}

View File

@ -1,11 +0,0 @@
package day.gitlab.dolphin.authorize.entity.vo;
import lombok.Data;
@Data
public class LoginVO {
private String accessToken;
private String refreshToken;
}

View File

@ -1,10 +0,0 @@
package day.gitlab.dolphin.authorize.service;
import day.gitlab.dolphin.authorize.entity.dto.LoginDTO;
import day.gitlab.dolphin.authorize.entity.vo.LoginVO;
import day.gitlab.dolphin.common.security.AuthenticationProvider;
public interface AuthorizeService extends AuthenticationProvider {
LoginVO login(LoginDTO loginDTO);
}

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>day.gitlab</groupId>
<artifactId>dolphin-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>dolphin-module-auth</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- 项目依赖 -->
<dependency>
<groupId>day.gitlab</groupId>
<artifactId>dolphin-common-security</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>day.gitlab</groupId>
<artifactId>dolphin-common-mybatis</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>day.gitlab</groupId>
<artifactId>dolphin-module-rbac</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MyBatis Flex -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,7 +1,7 @@
package day.gitlab.dolphin.authorize.controller;
package day.gitlab.dolphin.auth.controller;
import day.gitlab.dolphin.authorize.entity.dto.LoginDTO;
import day.gitlab.dolphin.authorize.service.AuthorizeService;
import day.gitlab.dolphin.auth.entity.dto.LoginDTO;
import day.gitlab.dolphin.auth.service.AuthService;
import day.gitlab.dolphin.common.core.entity.Result;
import day.gitlab.dolphin.common.security.annotation.AuthorityIgnore;
import jakarta.annotation.Resource;
@ -11,15 +11,15 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/authorize")
public class AuthorizeController {
@RequestMapping("/auth")
public class AuthController {
@Resource
private AuthorizeService authorizeService;
private AuthService authService;
@AuthorityIgnore
@PostMapping("/login")
public Result login(@RequestBody LoginDTO loginDTO) {
return Result.success(authorizeService.login(loginDTO));
return Result.success(authService.login(loginDTO));
}
}

View File

@ -0,0 +1,14 @@
package day.gitlab.dolphin.auth.entity.dto;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class LoginDTO {
@NotNull
private String username;
@NotNull
private String password;
}

View File

@ -0,0 +1,17 @@
package day.gitlab.dolphin.auth.entity.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class LoginVO {
private String accessToken;
private String refreshToken;
}

View File

@ -0,0 +1,9 @@
package day.gitlab.dolphin.auth.service;
import day.gitlab.dolphin.auth.entity.dto.LoginDTO;
import day.gitlab.dolphin.auth.entity.vo.LoginVO;
public interface AuthService {
LoginVO login(LoginDTO loginDTO);
}

View File

@ -1,16 +1,16 @@
package day.gitlab.dolphin.authorize.service.impl;
package day.gitlab.dolphin.auth.service.impl;
import cn.hutool.v7.crypto.digest.BCrypt;
import com.mybatisflex.core.query.QueryCondition;
import day.gitlab.dolphin.authorize.entity.dto.LoginDTO;
import day.gitlab.dolphin.authorize.entity.vo.LoginVO;
import day.gitlab.dolphin.authorize.service.AuthorizeService;
import day.gitlab.dolphin.auth.entity.dto.LoginDTO;
import day.gitlab.dolphin.auth.entity.vo.LoginVO;
import day.gitlab.dolphin.auth.service.AuthService;
import day.gitlab.dolphin.common.core.exception.BusinessException;
import day.gitlab.dolphin.common.security.AuthenticationProvider;
import day.gitlab.dolphin.common.security.UserPrincipal;
import day.gitlab.dolphin.common.security.jwt.JwtInfo;
import day.gitlab.dolphin.rbac.constants.UserEnabled;
import day.gitlab.dolphin.rbac.entity.Role;
import day.gitlab.dolphin.rbac.entity.User;
import day.gitlab.dolphin.rbac.entity.table.UserTableDef;
import day.gitlab.dolphin.rbac.mapper.UserMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
@ -20,7 +20,7 @@ import java.util.List;
import java.util.stream.Collectors;
@Service
public class AuthorizeServiceImpl implements AuthorizeService {
public class AuthServiceImpl implements AuthService, AuthenticationProvider {
@Resource
private UserMapper userMapper;
@ -28,6 +28,22 @@ public class AuthorizeServiceImpl implements AuthorizeService {
@Resource
private JwtInfo jwtInfo;
@Override
public LoginVO login(LoginDTO loginDTO) {
User dbUser = userMapper.findByUsername(loginDTO.getUsername());
if (dbUser == null || !BCrypt.checkpw(loginDTO.getPassword(), dbUser.getPassword())) {
throw new BusinessException("Username or password is incorrect");
}
if (!UserEnabled.ENABLED.equals(dbUser.getEnabled())) {
throw new BusinessException("User is not enabled");
}
return LoginVO.builder()
.accessToken(jwtInfo.generateAccessToken(dbUser.getId()))
.refreshToken(jwtInfo.generateRefreshToken(dbUser.getId()))
.build();
}
@Override
public UserPrincipal getUserPrincipal(String userId) {
User user = userMapper.selectOneById(userId);
@ -50,22 +66,4 @@ public class AuthorizeServiceImpl implements AuthorizeService {
return roles.stream().map(Role::getCode).collect(Collectors.toList());
}
@Override
public LoginVO login(LoginDTO loginDTO) {
QueryCondition queryCondition = UserTableDef.USER.USERNAME.eq(loginDTO.getUsername());
User user = userMapper.selectOneByCondition(queryCondition);
if (user == null || !BCrypt.checkpw(loginDTO.getPassword(), user.getPassword())) {
throw new BusinessException("User name or password is incorrect");
}
if (!"1".equalsIgnoreCase(user.getEnabled())) {
throw new BusinessException("User has been disabled");
}
LoginVO loginVO = new LoginVO();
loginVO.setAccessToken(jwtInfo.generateAccessToken(user.getId()));
loginVO.setRefreshToken(jwtInfo.generateRefreshToken(user.getId()));
return loginVO;
}
}

View File

@ -12,6 +12,7 @@
<packaging>jar</packaging>
<dependencies>
<!-- 项目依赖 -->
<dependency>
<groupId>day.gitlab</groupId>
<artifactId>dolphin-common-security</artifactId>
@ -22,20 +23,25 @@
<artifactId>dolphin-common-mybatis</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MyBatis Flex -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

View File

@ -7,8 +7,10 @@ import java.sql.Timestamp;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 字典 实体类。
@ -18,6 +20,8 @@ import lombok.Data;
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("sys_core_dictionary")
public class Dictionary implements Serializable {

View File

@ -7,8 +7,10 @@ import java.sql.Timestamp;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 字典项 实体类。
@ -18,6 +20,8 @@ import lombok.Data;
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("sys_core_dictionary_item")
public class DictionaryItem implements Serializable {

View File

@ -12,12 +12,36 @@
<packaging>jar</packaging>
<dependencies>
<!-- 项目依赖 -->
<dependency>
<groupId>day.gitlab</groupId>
<artifactId>dolphin-module-core</artifactId>
<artifactId>dolphin-common-security</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>day.gitlab</groupId>
<artifactId>dolphin-common-mybatis</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MyBatis Flex -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

View File

@ -0,0 +1,8 @@
package day.gitlab.dolphin.rbac.constants;
public class UserEnabled {
public static final String ENABLED = "1";
public static final String DISABLED = "0";
}

View File

@ -7,8 +7,10 @@ import java.sql.Timestamp;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 部门表 实体类。
@ -18,6 +20,8 @@ import lombok.Data;
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("sys_rbac_department")
public class Department implements Serializable {

View File

@ -7,8 +7,10 @@ import java.sql.Timestamp;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 区划项 实体类。
@ -18,6 +20,8 @@ import lombok.Data;
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("sys_rbac_region")
public class Region implements Serializable {

View File

@ -7,8 +7,10 @@ import java.sql.Timestamp;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 角色表 实体类。
@ -18,6 +20,8 @@ import lombok.Data;
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("sys_rbac_role")
public class Role implements Serializable {

View File

@ -9,8 +9,10 @@ import java.sql.Timestamp;
import java.io.Serial;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 用户表 实体类。
@ -20,6 +22,8 @@ import lombok.Data;
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("sys_rbac_user")
public class User implements Serializable {

View File

@ -14,5 +14,6 @@
<modules>
<module>dolphin-module-core</module>
<module>dolphin-module-rbac</module>
<module>dolphin-module-auth</module>
</modules>
</project>