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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<UserRole, Long> {
|
||||
|
||||
List<UserRole> queryAllByUsername(String username);
|
||||
}
|
||||
@@ -15,6 +15,8 @@ public enum ResponseCodeEnum implements BaseExceptionInterface {
|
||||
// ----------- 业务异常状态码 -----------
|
||||
LOGIN_FAIL("20000", "登录失败"),
|
||||
USERNAME_OR_PWD_ERROR("20001", "用户名或密码错误"),
|
||||
UNAUTHORIZED("20002", "无访问权限,请先登录!"),
|
||||
FORBIDDEN("20004", "演示账号仅支持查询操作!")
|
||||
;
|
||||
|
||||
// 异常码
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user