总是获取拒绝访问的异常,使用spring security@preauthorize

o8x7eapl  于 2021-07-13  发布在  Java
关注(0)|答案(0)|浏览(293)

基于会话的身份验证成功。之后,在授权时,我总是得到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>

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题