出现未经授权的错误:需要完全身份验证才能访问此资源

Posted

技术标签:

【中文标题】出现未经授权的错误:需要完全身份验证才能访问此资源【英文标题】:Getting Unauthorized error: Full authentication is required to access this resource 【发布时间】:2020-12-23 12:04:06 【问题描述】:

我正在实现JWTSpring Security 以在我的应用程序中进行身份验证。

我有 3 个角色:管理员、版主和用户。

例如,使用用户角色登录后,我得到了主页,但是一旦我通过点击进入用户空间在一个按钮上,我得到了:

2020-09-04 09:01:22.819 错误 10148 --- [nio-8080-exec-5] c.b.s.security.jwt.AuthEntryPointJwt:未经授权的错误:已满 访问此资源需要身份验证

文件webSecurityConfig.java是:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
    @Autowired
    UserDetailsServiceImpl userDetailsService;

    @Autowired
    private AuthEntryPointJwt unauthorizedHandler;

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() 
        return new AuthTokenFilter();
    

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception 
        authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception 
        return super.authenticationManagerBean();
    

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

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

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

AuthEntryPointJwt 类是:

@组件 公共类 AuthEntryPointJwt 实现 AuthenticationEntryPoint

  private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);

  @Override
  public void commence(HttpServletRequest request, HttpServletResponse response,
          AuthenticationException authException) throws IOException, ServletException 
      logger.error("Unauthorized error: ", authException.getMessage());
      response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
  

AuthTokenFilter 类是:

公共类 AuthTokenFilter 扩展 OncePerRequestFilter @自动连线 私有 JwtUtils jwtUtils;

  @Autowired
  private UserDetailsServiceImpl userDetailsService;

  private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class);

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
          throws ServletException, IOException 
      try 
          String jwt = parseJwt(request);
          if (jwt != null && jwtUtils.validateJwtToken(jwt)) 
              String username = jwtUtils.getUserNameFromJwtToken(jwt);

              UserDetails userDetails = userDetailsService.loadUserByUsername(username);
              UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                      userDetails, null, userDetails.getAuthorities());
              authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

              SecurityContextHolder.getContext().setAuthentication(authentication);
          
       catch (Exception e) 
          logger.error("Cannot set user authentication: ", e);
      

      filterChain.doFilter(request, response);
  

  private String parseJwt(HttpServletRequest request) 
      String headerAuth = request.getHeader("Authorization");

      if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) 
          return headerAuth.substring(7, headerAuth.length());
      

      return null;
  

JwtUtils 类是:

@组件 公共类 JwtUtils private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);

  @Value("$bezkoder.app.jwtSecret")
  private String jwtSecret;

  @Value("$bezkoder.app.jwtExpirationMs")
  private int jwtExpirationMs;

  public String generateJwtToken(Authentication authentication) 

      UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();

      return Jwts.builder()
              .setSubject((userPrincipal.getUsername()))
              .setIssuedAt(new Date())
              .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
              .signWith(SignatureAlgorithm.HS512, jwtSecret)
              .compact();
  

  public String getUserNameFromJwtToken(String token) 
      return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
  

  public boolean validateJwtToken(String authToken) 
      try 
          Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
          return true;
       catch (SignatureException e) 
          logger.error("Invalid JWT signature: ", e.getMessage());
       catch (MalformedJwtException e) 
          logger.error("Invalid JWT token: ", e.getMessage());
       catch (ExpiredJwtException e) 
          logger.error("JWT token is expired: ", e.getMessage());
       catch (UnsupportedJwtException e) 
          logger.error("JWT token is unsupported: ", e.getMessage());
       catch (IllegalArgumentException e) 
          logger.error("JWT claims string is empty: ", e.getMessage());
      

      return false;
  

AuthController 类是:

@CrossOrigin(origins = "*", maxAge = 3600) @RestController @RequestMapping("/api/auth") 公共类 AuthController @自动连线 AuthenticationManager authenticationManager;

      @Autowired
      UserRepository userRepository;

      @Autowired
      RoleRepository roleRepository;

      @Autowired
      PasswordEncoder encoder;

      @Autowired
      JwtUtils jwtUtils;

      @PostMapping("/signin")
      public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) 

          System.out.println("---------------- auth 1 ");
          Authentication authentication = authenticationManager.authenticate(
                  new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));

          SecurityContextHolder.getContext().setAuthentication(authentication);
          String jwt = jwtUtils.generateJwtToken(authentication);

          UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();      
          List<String> roles = userDetails.getAuthorities().stream()
                  .map(item -> item.getAuthority())
                  .collect(Collectors.toList());

          return ResponseEntity.ok(new JwtResponse(jwt, 
                                                   userDetails.getId(), 
                                                   userDetails.getUsername(), 
                                                   userDetails.getEmail(), 
                                                   roles));
      



      @GetMapping("/user")
      @PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')")
      public String userAccess()
      
          System.out.println("---------------- test User ");
          return "User Content.";
      
  

文件application.properties,我放:

spring.datasource.url=...
spring.datasource.username=...
spring.datasource.password=...
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation= true
spring.jpa.properties.hibernate.dialect=...
spring.jpa.hibernate.ddl-auto=update
bezkoder.app.jwtSecret= bezKoderSecretKey
bezkoder.app.jwtExpirationMs= 86400000

在浏览器控制台中,我得到了that exception。

您能帮我解决这个问题吗?非常感谢。

【问题讨论】:

您能否发布您的安全配置和控制器类。提供的信息不足以对此进行调试 您好@SridharPatnaik 先生,非常感谢您的回复。我对我的代码做了一些更改。请你看一下。非常感谢。 我也遇到了同样的问题,你能分享一下你是如何解决这个问题的吗? 【参考方案1】:

你应该评论@PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')")

说说结果?

【讨论】:

以上是关于出现未经授权的错误:需要完全身份验证才能访问此资源的主要内容,如果未能解决你的问题,请参考以下文章

HTTP 错误 401.2 - 未经授权 由于身份验证标头无效,您无权查看此页面

Spring Security OAuth - 访问此资源需要完全身份验证

401 - 在 IE7 中未经授权,仅使用 Windows 身份验证。

无法显示网页,错误代码:500 这是怎么回事?应该怎么办?

POST 请求“访问此资源需要完全身份验证”

浏览网页错误类型大全