From 0a126eb52068506321ffa4f9c363469c5b0c69ab Mon Sep 17 00:00:00 2001
From: Hanserwei <2628273921@qq.com>
Date: Sat, 29 Nov 2025 15:19:35 +0800
Subject: [PATCH] feat(security): implement JWT-based authentication and
authorization
- Configured JWT token validation filter in security chain
- Added user role mapping with new t_user_role table and UserRole entity
- Implemented custom authentication entry point and access denied handler
- Updated UserDetailService to load user roles from database
- Added @PreAuthorize annotation support for method-level security
- Refactored build scripts to use java-library plugin and proper dependency scope
- Enhanced SQL schema with user role table and improved table comments
- Added global exception handler for AccessDeniedException
- Introduced ResponseCodeEnum constants for unauthorized and forbidden access
- Integrated TokenAuthenticationFilter into Spring Security filter chain
---
.idea/data_source_mapping.xml | 6 ++
.idea/modules.xml | 2 +
sql/createTable.sql | 25 ++++-
weblog-module-admin/build.gradle.kts | 13 ++-
.../admin/config/WebSecurityConfig.java | 17 ++-
weblog-module-common/build.gradle.kts | 19 ++--
.../common/domain/dataobject/UserRole.java | 64 +++++++++++
.../domain/repository/UserRoleRepository.java | 11 ++
.../common/enums/ResponseCodeEnum.java | 2 +
.../exception/GlobalExceptionHandler.java | 8 ++
weblog-module-jwt/build.gradle.kts | 6 +-
.../JwtAuthenticationSecurityConfig.java | 7 ++
.../jwt/filter/TokenAuthenticationFilter.java | 101 ++++++++++++++++++
.../jwt/handler/RestAccessDeniedHandler.java | 26 +++++
.../handler/RestAuthenticationEntryPoint.java | 32 ++++++
.../jwt/service/UserDetailServiceImpl.java | 18 +++-
.../web/controller/TestController.java | 10 ++
17 files changed, 339 insertions(+), 28 deletions(-)
create mode 100644 .idea/data_source_mapping.xml
create mode 100644 weblog-module-common/src/main/java/com/hanserwei/common/domain/dataobject/UserRole.java
create mode 100644 weblog-module-common/src/main/java/com/hanserwei/common/domain/repository/UserRoleRepository.java
create mode 100644 weblog-module-jwt/src/main/java/com/hanserwei/jwt/filter/TokenAuthenticationFilter.java
create mode 100644 weblog-module-jwt/src/main/java/com/hanserwei/jwt/handler/RestAccessDeniedHandler.java
create mode 100644 weblog-module-jwt/src/main/java/com/hanserwei/jwt/handler/RestAuthenticationEntryPoint.java
diff --git a/.idea/data_source_mapping.xml b/.idea/data_source_mapping.xml
new file mode 100644
index 0000000..d636af0
--- /dev/null
+++ b/.idea/data_source_mapping.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index a93abb3..f6c1c36 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -5,6 +5,8 @@
+
+
\ No newline at end of file
diff --git a/sql/createTable.sql b/sql/createTable.sql
index e5c8e1c..30ef788 100644
--- a/sql/createTable.sql
+++ b/sql/createTable.sql
@@ -1,3 +1,5 @@
+-- ====================================================================================================================
+-- ====================================================================================================================
-- 1. 创建一个函数,用于在数据更新时自动修改 update_time 字段
CREATE OR REPLACE FUNCTION set_update_time()
RETURNS TRIGGER AS
@@ -7,7 +9,6 @@ BEGIN
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-
-- 2. 创建表(使用 BOOLEAN 替代 SMALLINT for is_deleted)
CREATE TABLE t_user
(
@@ -20,14 +21,30 @@ CREATE TABLE t_user
-- 使用 BOOLEAN 逻辑删除,DEFAULT FALSE 对应 '0:未删除'
is_deleted BOOLEAN NOT NULL DEFAULT FALSE
);
-
-- 3. 创建触发器,在每次 UPDATE 操作前调用函数
CREATE TRIGGER set_t_user_update_time
BEFORE UPDATE
ON t_user
FOR EACH ROW
EXECUTE FUNCTION set_update_time();
-
-- 添加注释
COMMENT ON TABLE t_user IS '用户表(优化版)';
-COMMENT ON COLUMN t_user.is_deleted IS '逻辑删除:FALSE:未删除 TRUE:已删除';
\ No newline at end of file
+COMMENT ON COLUMN t_user.is_deleted IS '逻辑删除:FALSE:未删除 TRUE:已删除';
+-- ====================================================================================================================
+-- ====================================================================================================================
+
+-- ====================================================================================================================
+-- ====================================================================================================================
+CREATE TABLE t_user_role
+(
+ id BIGSERIAL PRIMARY KEY,
+ username VARCHAR(60) NOT NULL,
+ role_name VARCHAR(60) NOT NULL, -- 重命名为 role_name 避免关键字冲突
+ create_time TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE INDEX idx_username ON t_user_role (username);
+
+COMMENT ON COLUMN t_user_role.role_name IS '角色名称';
+-- ====================================================================================================================
+-- ====================================================================================================================
\ No newline at end of file
diff --git a/weblog-module-admin/build.gradle.kts b/weblog-module-admin/build.gradle.kts
index 9c9b99c..9f6ec8b 100644
--- a/weblog-module-admin/build.gradle.kts
+++ b/weblog-module-admin/build.gradle.kts
@@ -1,15 +1,14 @@
plugins {
- java
+ `java-library`
}
dependencies {
- // Spring Security
- implementation("org.springframework.boot:spring-boot-starter-security")
- // Test
- testImplementation("org.springframework.boot:spring-boot-starter-test")
+ api("org.springframework.boot:spring-boot-starter-security")
implementation(project(":weblog-module-common"))
- implementation(project(":weblog-module-jwt"))
+ api(project(":weblog-module-jwt"))
+
+ testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.security:spring-security-test")
-}
\ No newline at end of file
+}
diff --git a/weblog-module-admin/src/main/java/com/hanserwei/admin/config/WebSecurityConfig.java b/weblog-module-admin/src/main/java/com/hanserwei/admin/config/WebSecurityConfig.java
index eca740a..2811e04 100644
--- a/weblog-module-admin/src/main/java/com/hanserwei/admin/config/WebSecurityConfig.java
+++ b/weblog-module-admin/src/main/java/com/hanserwei/admin/config/WebSecurityConfig.java
@@ -1,12 +1,15 @@
package com.hanserwei.admin.config;
import com.hanserwei.jwt.config.JwtAuthenticationSecurityConfig;
+import com.hanserwei.jwt.handler.RestAccessDeniedHandler;
+import com.hanserwei.jwt.handler.RestAuthenticationEntryPoint;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
@@ -17,11 +20,18 @@ import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
+@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig {
@Resource
private JwtAuthenticationSecurityConfig jwtAuthenticationSecurityConfig;
+ @Resource
+ private RestAccessDeniedHandler restAccessDeniedHandler;
+
+ @Resource
+ private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
+
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
@@ -38,7 +48,12 @@ public class WebSecurityConfig {
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
- // 5. 应用自定义配置 (核心变化)
+ // 5. 自定义未登录/权限不足的响应
+ .exceptionHandling(exception -> exception
+ .authenticationEntryPoint(restAuthenticationEntryPoint)
+ .accessDeniedHandler(restAccessDeniedHandler)
+ )
+ // 6. 应用自定义配置 (核心变化)
.with(jwtAuthenticationSecurityConfig, Customizer.withDefaults());
return http.build();
}
diff --git a/weblog-module-common/build.gradle.kts b/weblog-module-common/build.gradle.kts
index 03d0289..c3bcf76 100644
--- a/weblog-module-common/build.gradle.kts
+++ b/weblog-module-common/build.gradle.kts
@@ -4,21 +4,18 @@ plugins {
dependencies {
- // guava
implementation("com.google.guava:guava:33.5.0-jre")
- // commons-lang3
implementation("org.apache.commons:commons-lang3:3.20.0")
- // jpa
- api("org.springframework.boot:spring-boot-starter-data-jpa")
- // test
- testImplementation("org.springframework.boot:spring-boot-starter-test")
- // jackson
implementation("com.fasterxml.jackson.core:jackson-databind")
implementation("com.fasterxml.jackson.core:jackson-core")
- // aop
- implementation("org.springframework.boot:spring-boot-starter-aop")
- // web
+
+ api("org.springframework.boot:spring-boot-starter-data-jpa")
api("org.springframework.boot:spring-boot-starter-web")
- // postgresql
+ api("org.springframework.boot:spring-boot-starter-security")
+ api("org.springframework.boot:spring-boot-starter-aop")
+
runtimeOnly("org.postgresql:postgresql")
+
+ testImplementation("org.springframework.boot:spring-boot-starter-test")
+ testImplementation("org.springframework.security:spring-security-test")
}
diff --git a/weblog-module-common/src/main/java/com/hanserwei/common/domain/dataobject/UserRole.java b/weblog-module-common/src/main/java/com/hanserwei/common/domain/dataobject/UserRole.java
new file mode 100644
index 0000000..fc2e87a
--- /dev/null
+++ b/weblog-module-common/src/main/java/com/hanserwei/common/domain/dataobject/UserRole.java
@@ -0,0 +1,64 @@
+package com.hanserwei.common.domain.dataobject;
+
+import jakarta.persistence.*; // 使用 Jakarta Persistence API (JPA 3.0+)
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.CreationTimestamp;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.Instant;
+
+/**
+ * 用户角色表(t_user_role 对应实体)
+ */
+@Setter
+@Getter
+@Entity
+@Table(name = "t_user_role",
+ indexes = {
+ @Index(name = "idx_username", columnList = "username") // 映射数据库中的 idx_username 索引
+ })
+public class UserRole implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * ID (BIG SERIAL PRIMARY KEY)
+ */
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private Long id;
+
+ /**
+ * 用户名 (VARCHAR(60) NOT NULL)
+ */
+ @Column(name = "username", length = 60, nullable = false)
+ private String username;
+
+ /**
+ * 角色名称 (VARCHAR(60) NOT NULL)
+ */
+ @Column(name = "role_name", length = 60, nullable = false)
+ private String roleName;
+
+ /**
+ * 创建时间 (TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP)
+ */
+ @CreationTimestamp
+ @Column(name = "create_time", nullable = false, updatable = false)
+ private Instant createTime;
+
+ // --- 构造函数 (Constructor) ---
+
+ public UserRole() {
+ }
+
+ public UserRole(String username, String roleName) {
+ this.username = username;
+ this.roleName = roleName;
+ }
+
+}
\ No newline at end of file
diff --git a/weblog-module-common/src/main/java/com/hanserwei/common/domain/repository/UserRoleRepository.java b/weblog-module-common/src/main/java/com/hanserwei/common/domain/repository/UserRoleRepository.java
new file mode 100644
index 0000000..1611660
--- /dev/null
+++ b/weblog-module-common/src/main/java/com/hanserwei/common/domain/repository/UserRoleRepository.java
@@ -0,0 +1,11 @@
+package com.hanserwei.common.domain.repository;
+
+import com.hanserwei.common.domain.dataobject.UserRole;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface UserRoleRepository extends JpaRepository {
+
+ List queryAllByUsername(String username);
+}
diff --git a/weblog-module-common/src/main/java/com/hanserwei/common/enums/ResponseCodeEnum.java b/weblog-module-common/src/main/java/com/hanserwei/common/enums/ResponseCodeEnum.java
index 02e7128..d770a39 100644
--- a/weblog-module-common/src/main/java/com/hanserwei/common/enums/ResponseCodeEnum.java
+++ b/weblog-module-common/src/main/java/com/hanserwei/common/enums/ResponseCodeEnum.java
@@ -15,6 +15,8 @@ public enum ResponseCodeEnum implements BaseExceptionInterface {
// ----------- 业务异常状态码 -----------
LOGIN_FAIL("20000", "登录失败"),
USERNAME_OR_PWD_ERROR("20001", "用户名或密码错误"),
+ UNAUTHORIZED("20002", "无访问权限,请先登录!"),
+ FORBIDDEN("20004", "演示账号仅支持查询操作!")
;
// 异常码
diff --git a/weblog-module-common/src/main/java/com/hanserwei/common/exception/GlobalExceptionHandler.java b/weblog-module-common/src/main/java/com/hanserwei/common/exception/GlobalExceptionHandler.java
index 0b8f107..c9fe5be 100644
--- a/weblog-module-common/src/main/java/com/hanserwei/common/exception/GlobalExceptionHandler.java
+++ b/weblog-module-common/src/main/java/com/hanserwei/common/exception/GlobalExceptionHandler.java
@@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.security.access.AccessDeniedException;
import java.util.Optional;
@ControllerAdvice
@@ -76,4 +77,11 @@ public class GlobalExceptionHandler {
return Response.fail(errorCode, errorMessage);
}
+ @ExceptionHandler({ AccessDeniedException.class })
+ public void throwAccessDeniedException(AccessDeniedException e) throws AccessDeniedException {
+ // 捕获到鉴权失败异常,主动抛出,交给 RestAccessDeniedHandler 去处理
+ log.info("============= 捕获到 AccessDeniedException");
+ throw e;
+ }
+
}
\ No newline at end of file
diff --git a/weblog-module-jwt/build.gradle.kts b/weblog-module-jwt/build.gradle.kts
index bcb19b2..47a5255 100644
--- a/weblog-module-jwt/build.gradle.kts
+++ b/weblog-module-jwt/build.gradle.kts
@@ -2,12 +2,10 @@ plugins {
`java-library`
}
-group = "com.hanserwei.jwt"
-version = project.parent?.version ?: "0.0.1-SNAPSHOT"
-
dependencies {
- implementation("org.springframework.boot:spring-boot-starter-security")
+ api("org.springframework.boot:spring-boot-starter-security")
implementation(project(":weblog-module-common"))
+ implementation("org.apache.commons:commons-lang3:3.20.0")
// jwt
api(libs.jjwt.api)
diff --git a/weblog-module-jwt/src/main/java/com/hanserwei/jwt/config/JwtAuthenticationSecurityConfig.java b/weblog-module-jwt/src/main/java/com/hanserwei/jwt/config/JwtAuthenticationSecurityConfig.java
index 89e4c97..96cb19d 100644
--- a/weblog-module-jwt/src/main/java/com/hanserwei/jwt/config/JwtAuthenticationSecurityConfig.java
+++ b/weblog-module-jwt/src/main/java/com/hanserwei/jwt/config/JwtAuthenticationSecurityConfig.java
@@ -1,6 +1,7 @@
package com.hanserwei.jwt.config;
import com.hanserwei.jwt.filter.JwtAuthenticationFilter;
+import com.hanserwei.jwt.filter.TokenAuthenticationFilter;
import com.hanserwei.jwt.handler.RestAuthenticationFailureHandler;
import com.hanserwei.jwt.handler.RestAuthenticationSuccessHandler;
import jakarta.annotation.Resource;
@@ -20,6 +21,9 @@ public class JwtAuthenticationSecurityConfig extends SecurityConfigurerAdapter claimsJws = jwtTokenHelper.parseToken(token);
+
+ // 4. 获取用户名
+ // JJWT 0.12+ 建议使用 getPayload() 替代 getBody()
+ // 在 Helper 中生成 Token 时使用的是 .subject(username),所以这里取 Subject
+ String username = claimsJws.getPayload().getSubject();
+
+ // 5. 组装认证信息 (如果当前上下文没有认证信息)
+ if (StringUtils.isNotBlank(username) && Objects.isNull(SecurityContextHolder.getContext().getAuthentication())) {
+
+ // 查询数据库获取用户完整信息 (包含权限)
+ UserDetails userDetails = userDetailsService.loadUserByUsername(username);
+
+ // 构建 Spring Security 的认证 Token
+ UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
+ userDetails,
+ null,
+ userDetails.getAuthorities()
+ );
+
+ authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+
+ // 6. 将认证信息存入 SecurityContext
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ }
+ } catch (AuthenticationException e) {
+ // 7. 异常处理
+ // 捕获 JwtTokenHelper 抛出的 BadCredentialsException 或 CredentialsExpiredException
+ // 如果 Token 存在但是无效/过期,直接交给 EntryPoint 处理响应 (通常返回 401)
+ // 并 return 结束当前过滤器,不再往下执行
+ authenticationEntryPoint.commence(request, response, e);
+ return;
+ } catch (Exception e) {
+ // 处理其他未预料到的异常
+ log.error("JWT处理过程中发生未知错误", e);
+ authenticationEntryPoint.commence(request, response, new AuthenticationException("系统内部认证错误") {
+ });
+ return;
+ }
+ }
+ }
+
+ // 8. 放行请求 (如果没有 Token 或者 Token 校验通过,继续执行下一个过滤器)
+ filterChain.doFilter(request, response);
+ }
+}
\ No newline at end of file
diff --git a/weblog-module-jwt/src/main/java/com/hanserwei/jwt/handler/RestAccessDeniedHandler.java b/weblog-module-jwt/src/main/java/com/hanserwei/jwt/handler/RestAccessDeniedHandler.java
new file mode 100644
index 0000000..e0e88cb
--- /dev/null
+++ b/weblog-module-jwt/src/main/java/com/hanserwei/jwt/handler/RestAccessDeniedHandler.java
@@ -0,0 +1,26 @@
+package com.hanserwei.jwt.handler;
+
+import com.hanserwei.common.enums.ResponseCodeEnum;
+import com.hanserwei.common.utils.Response;
+import com.hanserwei.jwt.utils.ResultUtil;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+@Slf4j
+@Component
+public class RestAccessDeniedHandler implements AccessDeniedHandler {
+
+ @Override
+ public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
+ log.warn("登录成功访问收保护的资源,但是权限不够: ", accessDeniedException);
+ // 预留,后面引入多角色时会用到
+ ResultUtil.fail(response, Response.fail(ResponseCodeEnum.FORBIDDEN));
+ }
+}
diff --git a/weblog-module-jwt/src/main/java/com/hanserwei/jwt/handler/RestAuthenticationEntryPoint.java b/weblog-module-jwt/src/main/java/com/hanserwei/jwt/handler/RestAuthenticationEntryPoint.java
new file mode 100644
index 0000000..f851e3f
--- /dev/null
+++ b/weblog-module-jwt/src/main/java/com/hanserwei/jwt/handler/RestAuthenticationEntryPoint.java
@@ -0,0 +1,32 @@
+package com.hanserwei.jwt.handler;
+
+import com.hanserwei.common.enums.ResponseCodeEnum;
+import com.hanserwei.common.utils.Response;
+import com.hanserwei.jwt.utils.ResultUtil;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+@Slf4j
+@Component
+public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
+ log.warn("用户未登录访问受保护的资源: ", authException);
+ if (authException instanceof InsufficientAuthenticationException) {
+ ResultUtil.fail(response, HttpStatus.UNAUTHORIZED.value(), Response.fail(ResponseCodeEnum.UNAUTHORIZED));
+ return;
+ }
+
+ ResultUtil.fail(response, HttpStatus.UNAUTHORIZED.value(), Response.fail(authException.getMessage()));
+ }
+}
diff --git a/weblog-module-jwt/src/main/java/com/hanserwei/jwt/service/UserDetailServiceImpl.java b/weblog-module-jwt/src/main/java/com/hanserwei/jwt/service/UserDetailServiceImpl.java
index 4f521c2..ab887f3 100644
--- a/weblog-module-jwt/src/main/java/com/hanserwei/jwt/service/UserDetailServiceImpl.java
+++ b/weblog-module-jwt/src/main/java/com/hanserwei/jwt/service/UserDetailServiceImpl.java
@@ -1,14 +1,18 @@
package com.hanserwei.jwt.service;
import com.hanserwei.common.domain.dataobject.User;
+import com.hanserwei.common.domain.dataobject.UserRole;
import com.hanserwei.common.domain.repository.UserRepository;
+import com.hanserwei.common.domain.repository.UserRoleRepository;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import java.util.List;
import java.util.Objects;
@Service
@@ -18,6 +22,9 @@ public class UserDetailServiceImpl implements UserDetailsService {
@Resource
private UserRepository userRepository;
+ @Resource
+ private UserRoleRepository userRoleRepository;
+
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 从数据库查询用户信息
@@ -27,10 +34,19 @@ public class UserDetailServiceImpl implements UserDetailsService {
throw new UsernameNotFoundException("用户不存在");
}
+ List userRoles = userRoleRepository.queryAllByUsername(username);
+ // 转换为数组
+ String[] roleArr = new String[0];
+ if (!CollectionUtils.isEmpty(userRoles)) {
+ roleArr = userRoles.stream()
+ .map(UserRole::getRoleName)
+ .toArray(String[]::new);
+ }
+
// authorities 用于指定角色,这里写死为 ADMIN 管理员
return org.springframework.security.core.userdetails.User.withUsername(user.getUsername())
.password(user.getPassword())
- .authorities("ADMIN")
+ .authorities(roleArr)
.build();
}
}
\ No newline at end of file
diff --git a/weblog-web/src/main/java/com/hanserwei/web/controller/TestController.java b/weblog-web/src/main/java/com/hanserwei/web/controller/TestController.java
index 4735912..f3783c8 100644
--- a/weblog-web/src/main/java/com/hanserwei/web/controller/TestController.java
+++ b/weblog-web/src/main/java/com/hanserwei/web/controller/TestController.java
@@ -1,9 +1,11 @@
package com.hanserwei.web.controller;
import com.hanserwei.common.aspect.ApiOperationLog;
+import com.hanserwei.common.utils.Response;
import com.hanserwei.web.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
@@ -35,4 +37,12 @@ public class TestController {
return ResponseEntity.ok("参数没有任何问题");
}
+ @PostMapping("/admin/update")
+ @ApiOperationLog(description = "测试更新接口")
+ @PreAuthorize("hasRole('ROLE_ADMIN')")
+ public Response> testUpdate() {
+ log.info("更新成功...");
+ return Response.success();
+ }
+
}
\ No newline at end of file