【问题标题】:Error: Full authentication is required to access this resource when using @PreAuthorize错误:使用 @PreAuthorize 时需要完全身份验证才能访问此资源
【发布时间】:2021-10-21 13:51:26
【问题描述】:

我正在尝试使用 Spring Boot、带有角色的 JWT 实现身份验证

我有错误:

访问此资源需要完整的身份验证

发送 POST 请求时 到“http://localhost:8080/api/profile/edit_user_detail”(带有授权标头)

下面是我的控制器

@Controller
@CrossOrigin(origins = "*",maxAge = 3600)
@RequestMapping("/api/profile")
public class UserAPI {

    @Autowired
    UserRepository userRepository;
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    QARepository qaRepository;
    @Autowired
    DiscussRepository discussRepository;
    @Autowired
    AnnouncementRepository announcementRepository;

    @PostMapping(value = {"/edit_user_detail"})
    @PreAuthorize("hasRole('ROLE_USER')")
    public ResponseEntity<?> editInfo(@RequestBody Map map) throws ParseException {
        String username = map.get("username").toString();
        String display_name = map.get("display_name").toString();

        User user = userRepository.findByUserName(username).get(0);
        user.setuDigitalName(display_name);
       
        userRepository.save(user);

        return ResponseEntity.ok("Updated");
    }

但是当我删除线时

@PreAuthorize("hasRole('ROLE_USER')")

然后我可以成功发布请求并成功编辑用户(我已签入数据库)

这也是我的入口点(捕捉异常)

@Component
public class AuthEntryPointJwt implements AuthenticationEntryPoint {
    private static final Logger log = LoggerFactory.getLogger(AuthEntryPointJwt.class);
    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        log.error("Authorized error: " + e.getMessage());
        httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Error: Unauthorized");
        e.printStackTrace();
    }
}

这是我的配置文件

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ConfigAuthenticate extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServices userDetailsServices;

    @Autowired
    private AuthEntryPointJwt unauthorizeHandler;

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter(){
        return new AuthTokenFilter();
    }
    @Bean
    @Override public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsServices).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizeHandler)
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeRequests()
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated();

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }

}

我认为 WebSecurityConfigurerAdapter 中的配置有问题,我已尝试

  • @PreAuthorize("hasRole('ROLE_USER')") 更改为@PreAuthorize("hasRole('USER')")
  • 检查标头中的 JWT Token,以及数据库中的 ROLE

还是不行,谁有解决办法

【问题讨论】:

    标签: java authentication jwt postman


    【解决方案1】:

    尝试删除.antMatchers("/**").permitAll(),并将这些行添加到您的:

    application.yml

    logging:
      level:
        org.springframework.security: TRACE
    

    或application.properties

    logging.level.org.springframework.security=TRACE
    

    您可以像这样看到有关您的用户的信息:

    AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]]
    

    您可以依靠Granted Authorities 来确定用户的角色


    因为您在.anyRequest().authenticated() 之前设置了.antMatchers("/**").permitAll(),所以我不确定您是否成功验证了用户。如果没有,那么AnonymousAuthenticationFilter 将为您创建一个匿名用户。如果你不添加@PreAuthorize("hasRole('USER')")FilterSecurityInterceptor,基于​​.antMatchers("/**").permitAll(),将允许请求通过它并访问控制器。

    【讨论】:

    • 感谢您的回复,我已经检查过,这是真的,当我更改为 @PreAuthorize("hasRole('ROLE_ANONYMOUS')") 时它可以工作,但我这样任何人(包括不登录的人) ) 可以使用这个 api。我想在这里检查我在登录响应中的ROLE_USER,任何想法{“token”:“eyJhbGciOiJIUzUxMiJ9.e ...”,“type”:“Bearer”,“id”:1,“username”:“tin ", "电子邮件": "tin@gmail.com", "角色": [ "ROLE_USER" ] }
    • @Đoàn 这取决于你的过滤器实现,我看到你设置了http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);。所以这里的责任属于你的AuthTokenFilter,我不知道但我想提出的一件事是在你成功验证你的用户或检查你有没有之后不要忘记设置SecurityContext它通过实现一些抽象过滤器。例如:``` 身份验证 auth = ...; SecurityContextHolder.getContext().setAuthentication(auth); ```
    • 非常正确,我忘了设置SecurityContext:SecurityContextHolder.getContext().setAuthentication(...);。问题已解决,非常感谢
    猜你喜欢
    • 2018-06-29
    • 2015-11-03
    • 2020-03-30
    • 2019-02-02
    • 2020-10-25
    • 2020-12-23
    • 2016-10-03
    • 2023-02-21
    • 2017-06-30
    相关资源
    最近更新 更多