出现未经授权的错误:需要完全身份验证才能访问此资源
Posted
技术标签:
【中文标题】出现未经授权的错误:需要完全身份验证才能访问此资源【英文标题】:Getting Unauthorized error: Full authentication is required to access this resource 【发布时间】:2020-12-23 12:04:06 【问题描述】:我正在实现JWT
和Spring 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 - 访问此资源需要完全身份验证