【问题标题】: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 先生,非常感谢您的回复。我对我的代码做了一些更改。请你看一下。非常感谢。
  • 我也遇到了同样的问题,你能分享一下你是如何解决这个问题的吗?

标签: reactjs spring-boot spring-security jwt


【解决方案1】:

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

说说结果?

【讨论】:

    猜你喜欢
    • 2018-06-29
    • 2020-09-02
    • 2022-07-22
    • 2018-06-04
    • 1970-01-01
    • 2021-01-24
    • 2015-11-03
    • 2020-03-30
    • 2022-07-20
    相关资源
    最近更新 更多