基于会话的身份验证成功。之后,在授权时,我总是得到403禁止,并显示以下错误消息:“拒绝用户myuser对object null的权限'perm\u do\u something'”—其中'myuser'是我从会话中获得的用户名,'perm\u do\u something'来自haspowersion的属性,来自controller的@preauthorize。
我在控制器中使用了@preauthorize注解:
@PreAuthorize("hasPermission(#something, 'PERM_DO_SOMETHING')")
@GetMapping("/users")
public ResponseEntity<?> getListOfUsers() {
return (ResponseEntity<?>) ResponseEntity.ok();
}
当前用户已成功通过authcookiefilter扩展genericfilterbean的身份验证。
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
MyUserPrincipal userPrincipal;
String sessionPayload = extractAuthenticationCookie(request);
if(sessionPayload != null) {
Session session = sessionRepository.getSessionByPayload(sessionPayload);
String userName = session.getUsername();
userPrincipal = service.loadUserByUsername(userName);
if (userPrincipal.getUsername() != null) {
SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(userPrincipal));
}
}
refreshCookie(request, response);
filterChain.doFilter(servletRequest, servletResponse);
}
loaduserbyusername函数来自实现userdetailsservice的userdetailsserviceimpl:
@Override
public MyUserPrincipal loadUserByUsername(String username) {
Optional<User> optionalUser = userRepository.findByUsername(username);
if (optionalUser.isPresent()) {
User user = optionalUser.get();
return new MyUserPrincipal(user);
}
throw new UsernameNotFoundException(username);
}
myuserprincipal公司:
public class MyUserPrincipal implements UserDetails {
User user;
public MyUserPrincipal(User user) {
this.user = user;
}
@Override
public String getUsername() {
return user.getUserName();
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public String getPassword() {
return user.getUserPassword();
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
for (Role role : user.getRoles()) {
authorities.add(new SimpleGrantedAuthority(role.getRoleName()));
}
for (Permission permission : user.getPermissions()) {
authorities.add(new SimpleGrantedAuthority(permission.getPermissionName()));
}
return authorities;
}
}
用户身份验证:
public class UserAuthentication implements Authentication {
private static final long serialVersionUID = 1L;
private final MyUserPrincipal userPrincipal;
public UserAuthentication(MyUserPrincipal userPrincipal) {
this.userPrincipal = userPrincipal;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
return (Collection<GrantedAuthority>) userPrincipal.getAuthorities();
}
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getDetails() {
return null;
}
@Override
public Object getPrincipal() {
return userPrincipal;
}
@Override
public boolean isAuthenticated() {
return true;
}
@Override
public void setAuthenticated(boolean b) throws IllegalArgumentException {
throw new UnsupportedOperationException("this authentication object is always authenticated");
}
@Override
public String getName() {
return userPrincipal.getUsername();
}
}
与“myuser”相关的权限存储在数据库中,它们的名称是:role\u something\u something或perm\u do\u something。
我实现了permissionevaluator:
public class PermissionEvaluatorImpl implements PermissionEvaluator {
@Override
public boolean hasPermission(
Authentication auth, Object targetDomainObject, Object permission) {
if ((auth == null) || (targetDomainObject == null) || !(permission instanceof String)){
return false;
}
String targetType = targetDomainObject.getClass().getSimpleName().toUpperCase();
return hasPrivilege(auth, targetType, permission.toString().toUpperCase());
}
@Override
public boolean hasPermission(
Authentication auth, Serializable targetId, String targetType, Object permission) {
if ((auth == null) || (targetType == null) || !(permission instanceof String)) {
return false;
}
return hasPrivilege(auth, targetType.toUpperCase(),
permission.toString().toUpperCase());
}
private boolean hasPrivilege(Authentication auth, String targetType, String permission) {
for (GrantedAuthority grantedAuth : auth.getAuthorities()) {
if (grantedAuth.getAuthority().startsWith(targetType)) {
if (grantedAuth.getAuthority().contains(permission)) {
return true;
}
}
}
return false;
}
}
以及以下配置:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler =
new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new PermissionEvaluatorImpl());
return expressionHandler;
}
}
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
AuthCookieFilter authCookieFilter;
LogoutSuccessHandler logoutSuccessHandler;
@Autowired
public WebSecurityConfig(AuthCookieFilter authCookieFilter,
LogoutSuccessHandler logoutSuccessHandler) {
this.authCookieFilter = authCookieFilter;
this.logoutSuccessHandler = logoutSuccessHandler;
}
@Bean
public FilterRegistrationBean<AuthCookieFilter> myFilterRegistrationBean() {
FilterRegistrationBean<AuthCookieFilter> regBean = new FilterRegistrationBean();
regBean.setFilter(authCookieFilter);
return regBean;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.headers(cust -> cust.contentSecurityPolicy(
"script-src 'self'; object-src 'none'; base-uri 'self'"
))
.csrf().disable()
.logout().addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(ClearSiteDataHeaderWriter.Directive.ALL)))
.logoutSuccessHandler(logoutSuccessHandler)
.deleteCookies(AuthCookieFilter.COOKIE_NAME)
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.and()
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and()
.addFilterAfter(authCookieFilter, SecurityContextPersistenceFilter.class);
}
}
以下注解主要用于:
@SpringBootApplication
@ComponentScan(excludeFilters =
{@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = GlobalMethodSecurityConfiguration.class)})
public class SpringSecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SpringSecurityApplication.class, args);
}
}
我的依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<dependencies>
暂无答案!
目前还没有任何答案,快来回答吧!