本文目录导读:

我来详细讲解Spring Security中基于角色和权限的授权机制。
核心概念
角色(Role) vs 权限(Permission)
// 角色通常是粗粒度的权限集合
public enum Role {
ADMIN, MANAGER, USER, GUEST
}
// 权限是细粒度的操作控制
public enum Permission {
USER_CREATE, USER_READ, USER_UPDATE, USER_DELETE,
ORDER_CREATE, ORDER_READ, ORDER_UPDATE, ORDER_DELETE
}
基础配置示例
内存用户配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password(passwordEncoder().encode("admin123"))
.roles("ADMIN")
.authorities("ROLE_ADMIN", "USER_CREATE", "USER_DELETE")
.and()
.withUser("manager")
.password(passwordEncoder().encode("manager123"))
.roles("MANAGER")
.authorities("ROLE_MANAGER", "USER_READ")
.and()
.withUser("user")
.password(passwordEncoder().encode("user123"))
.roles("USER")
.authorities("ROLE_USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
// 基于角色的URL安全
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/manager/**").hasAnyRole("ADMIN", "MANAGER")
.antMatchers("/user/**").hasAnyRole("ADMIN", "MANAGER", "USER")
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
数据库权限模型
数据库表结构
-- 用户表
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
enabled BOOLEAN DEFAULT true
);
-- 角色表
CREATE TABLE roles (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL UNIQUE
);
-- 权限表
CREATE TABLE permissions (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL UNIQUE
);
-- 用户-角色关联表
CREATE TABLE user_roles (
user_id BIGINT,
role_id BIGINT,
PRIMARY KEY (user_id, role_id),
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (role_id) REFERENCES roles(id)
);
-- 角色-权限关联表
CREATE TABLE role_permissions (
role_id BIGINT,
permission_id BIGINT,
PRIMARY KEY (role_id, permission_id),
FOREIGN KEY (role_id) REFERENCES roles(id),
FOREIGN KEY (permission_id) REFERENCES permissions(id)
);
用户实体和权限服务
@Entity
@Table(name = "users")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(nullable = false)
private String password;
private boolean enabled = true;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authorities = new HashSet<>();
// 添加角色(注意ROLE_前缀)
roles.forEach(role -> {
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
// 添加角色对应的权限
role.getPermissions().forEach(permission -> {
authorities.add(new SimpleGrantedAuthority(permission.getName()));
});
});
return authorities;
}
// 其他UserDetails方法实现...
}
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "role_permissions",
joinColumns = @JoinColumn(name = "role_id"),
inverseJoinColumns = @JoinColumn(name = "permission_id")
)
private Set<Permission> permissions = new HashSet<>();
}
@Entity
@Table(name = "permissions")
public class Permission {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
自定义UserDetailsService
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));
}
}
方法级安全注解
基于角色的注解
@RestController
public class UserController {
// 只有ADMIN角色可以访问
@GetMapping("/api/users")
@Secured("ROLE_ADMIN")
public List<User> getAllUsers() {
return userService.findAll();
}
// ADMIN或MANAGER角色可以访问
@GetMapping("/api/users/{id}")
@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
基于权限的注解(推荐方式)
@RestController
@RequestMapping("/api")
public class AdminController {
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userService.create(user);
}
@PreAuthorize("hasAuthority('USER_DELETE')")
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
userService.delete(id);
}
@PreAuthorize("hasAnyAuthority('USER_READ', 'USER_UPDATE')")
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
// 复杂条件表达式
@PreAuthorize("hasRole('ADMIN') and hasAuthority('USER_CREATE')")
@PutMapping("/users/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
return userService.update(id, user);
}
// 基于对象属性的权限控制
@PostAuthorize("returnObject.owner == authentication.name")
@GetMapping("/documents/{id}")
public Document getDocument(@PathVariable Long id) {
return documentService.findById(id);
}
}
动态权限控制
实现AccessDecisionManager
@Component
public class CustomAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object object,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes == null || configAttributes.isEmpty()) {
return;
}
for (ConfigAttribute configAttribute : configAttributes) {
String needAuthority = configAttribute.getAttribute();
for (GrantedAuthority ga : authentication.getAuthorities()) {
if (needAuthority.equals(ga.getAuthority())) {
return;
}
}
}
throw new AccessDeniedException("Access denied");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
自定义权限评估
@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
@Override
public boolean hasPermission(Authentication authentication,
Object targetDomainObject,
Object permission) {
if (authentication == null || !authentication.isAuthenticated()) {
return false;
}
// 检查用户是否有特定权限
if (targetDomainObject instanceof User) {
User user = (User) targetDomainObject;
String permissionStr = permission.toString();
return authentication.getAuthorities()
.stream()
.anyMatch(a -> a.getAuthority().equals(permissionStr));
}
return false;
}
@Override
public boolean hasPermission(Authentication authentication,
Serializable targetId,
String targetType,
Object permission) {
// 基于ID的权限检查
if ("USER".equals(targetType)) {
return hasPermission(authentication,
userService.findById((Long) targetId), permission);
}
return false;
}
}
实际应用示例
基于RBAC的完整实现
@Service
public class RBACService {
@PreAuthorize("hasRole('ADMIN')")
public void assignRoleToUser(Long userId, String roleName) {
// 分配角色给用户
}
@PreAuthorize("hasRole('ADMIN')")
public void revokeRoleFromUser(Long userId, String roleName) {
// 撤销用户角色
}
@PreAuthorize("hasRole('ADMIN')")
public void grantPermissionToRole(String roleName, String permissionName) {
// 给角色授予权限
}
// 检查用户是否有操作权限
public boolean userHasPermission(Long userId, String permissionName) {
User user = userRepository.findById(userId).orElseThrow();
return user.getAuthorities().stream()
.anyMatch(a -> a.getAuthority().equals(permissionName));
}
// 获取用户的所有角色
public Set<String> getUserRoles(Long userId) {
User user = userRepository.findById(userId).orElseThrow();
return user.getRoles().stream()
.map(Role::getName)
.collect(Collectors.toSet());
}
// 获取用户的所有权限
public Set<String> getUserPermissions(Long userId) {
User user = userRepository.findById(userId).orElseThrow();
Set<String> permissions = new HashSet<>();
user.getRoles().forEach(role -> {
role.getPermissions().forEach(permission -> {
permissions.add(permission.getName());
});
});
return permissions;
}
}
API权限验证
@RestController
@RequestMapping("/api/v1")
public class DocumentController {
@PreAuthorize("hasAnyRole('ADMIN', 'MANAGER')")
@GetMapping("/documents")
public ResponseEntity<List<Document>> getAllDocuments() {
return ResponseEntity.ok(documentService.findAll());
}
@PreAuthorize("@customPermissionEvaluator.hasPermission(authentication, #id, 'DOCUMENT', 'READ')")
@GetMapping("/documents/{id}")
public ResponseEntity<Document> getDocument(@PathVariable Long id) {
return ResponseEntity.ok(documentService.findById(id));
}
@PreAuthorize("hasAuthority('DOCUMENT_CREATE')")
@PostMapping("/documents")
public ResponseEntity<Document> createDocument(@RequestBody Document document) {
return ResponseEntity.ok(documentService.create(document));
}
@PreAuthorize("hasAuthority('DOCUMENT_UPDATE')")
@PutMapping("/documents/{id}")
public ResponseEntity<Document> updateDocument(@PathVariable Long id,
@RequestBody Document document) {
return ResponseEntity.ok(documentService.update(id, document));
}
@PreAuthorize("hasAuthority('DOCUMENT_DELETE')")
@DeleteMapping("/documents/{id}")
public ResponseEntity<Void> deleteDocument(@PathVariable Long id) {
documentService.delete(id);
return ResponseEntity.ok().build();
}
}
最佳实践建议
权限设计原则
@Component
public class PermissionConstants {
// 命名规范:资源_操作
public static final String USER_CREATE = "USER_CREATE";
public static final String USER_READ = "USER_READ";
public static final String USER_UPDATE = "USER_UPDATE";
public static final String USER_DELETE = "USER_DELETE";
public static final String ORDER_CREATE = "ORDER_CREATE";
public static final String ORDER_READ = "ORDER_READ";
public static final String ORDER_UPDATE = "ORDER_UPDATE";
// 角色前缀
public static final String ROLE_PREFIX = "ROLE_";
}
安全审计
@Aspect
@Component
public class SecurityAuditAspect {
@AfterReturning("@annotation(preAuthorize)")
public void auditAccess(JoinPoint joinPoint, PreAuthorize preAuthorize) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
AuditLog auditLog = new AuditLog();
auditLog.setUsername(auth.getName());
auditLog.setMethod(joinPoint.getSignature().getName());
auditLog.setExpression(preAuthorize.value());
auditLog.setTimestamp(LocalDateTime.now());
auditLog.setSuccess(true);
auditLogRepository.save(auditLog);
}
}
基于角色和权限的授权机制是Spring Security的核心功能,通过合理的权限设计和配置,可以实现灵活、安全的访问控制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播