我在实现角色和权限逻辑方面遇到了障碍。
注册为管理员并成功进行身份验证后,我尝试使用身份验证期间生成的令牌访问特定于管理员角色的端点。但是,我不断收到 403 Forbidden 错误。
您能看一下并帮我找出可能缺少或不正确的内容吗?
代码:
管理控制器
@RestController
@RequestMapping(path = "/api/v1/Admin")
//@PreAuthorize("hasRole('ADMIN')")
public class AdminController {
private final AnoUserService anoUserService;
@Autowired
public AdminController(AnoUserService anoUserService) {
this.anoUserService = anoUserService;
@GetMapping("/hello")
public String hello(){
return "Hello admin";
}
}
弹簧配置
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
http
.cors(withDefaults())
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(req ->
req.requestMatchers(
"/api/v1/auth/**",
).permitAll()
.requestMatchers("/api/v1/Admin/**").hasRole(ADMIN.name())//securing the admin endpoint
//then securing the different operations
.requestMatchers(GET,"/api/v1/Admin/**").hasAuthority(ADMIN_READ.name())
.requestMatchers(POST,"/api/v1/Admin/**").hasAuthority(ADMIN_CREATE.name())
.requestMatchers(PUT,"/api/v1/Admin/**").hasAuthority(ADMIN_UPDATE.name())
.requestMatchers(DELETE,"/api/v1/Admin/**").hasAuthority(ADMIN_DELETE.name())
.anyRequest()
.authenticated()
)
.sessionManagement(session -> session.sessionCreationPolicy(STATELESS))
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
枚举角色类:
package com.example.PFA.anoUser;
//import com.example.PFA.role.Role;
//import com.example.PFA.role.RoleRepository;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static com.example.PFA.anoUser.Permission.*;
@RequiredArgsConstructor
public enum EnumRole {
USER(Collections.emptySet()),
ADMIN(
Set.of(
ADMIN_READ,
ADMIN_CREATE,
ADMIN_UPDATE,
ADMIN_DELETE
)
);
@Getter
private final Set<Permission> permissions;
public List<SimpleGrantedAuthority> getAuthorities(){
var authorities = this.getPermissions()
.stream()
.map(permission ->new SimpleGrantedAuthority(permission.getPermission()) )
.collect(Collectors.toList());
authorities.add(new SimpleGrantedAuthority("ROLE_" + this.name()));
return authorities;
}
}
如果您的
Role
是Admin
,那么专用的Authority
就是ROLE_Admin
。您可以手动配置前缀,但默认情况下就是这样。由于您要通过 Authority
检查 #hasAuthority()
,因此您必须在前面添加 Role
前缀,而您没有。因此,您可以为枚举值添加前缀,或者在您的情况下更简单,只需使用 #hasRole
而不是 hasAuthority
:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
http
.cors(withDefaults())
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(req ->
req.requestMatchers("/api/v1/auth/**").permitAll()
.requestMatchers("/api/v1/Admin/**").hasRole(ADMIN.name())
.requestMatchers(GET,"/api/v1/Admin/**").hasRole(ADMIN_READ.name())
.requestMatchers(POST,"/api/v1/Admin/**").hasRole(ADMIN_CREATE.name())
.requestMatchers(PUT,"/api/v1/Admin/**").hasRole(ADMIN_UPDATE.name())
.requestMatchers(DELETE,"/api/v1/Admin/**").hasRole(ADMIN_DELETE.name())
.anyRequest().authenticated())
.sessionManagement(session -> session.sessionCreationPolicy(STATELESS))
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}