当前位置: 首页 > 知识库问答 >
问题:

Spring Security-401未经授权的访问

朱博实
2023-03-14

只要我的antMatcher上有.permitall(),这就可以很好地工作,但是当我试图保护它以便只有管理员才能进行该调用时(DB中的管理员角色是ROLE_ADMIN),它会返回401未经授权的访问,并且没有消息。我试过了

  • .hasRole(“admin”)
  • .hasRole(“role_admin”)
  • .hasAuthority(“admin”)
  • .hasAuthority(“role_admin”)

我的请求如下所示(为标题张贴):

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
    securedEnabled = true,
    jsr250Enabled = true,
    prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
UserDetailsServiceImpl userDetailsService;

@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;

@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
    return new JwtAuthenticationFilter();
}

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

@Bean(BeanIds.AUTHENTICATION_MANAGER)
@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("/",
                    "/favicon.ico",
                    "/**/*.png",
                    "/**/*.gif",
                    "/**/*.svg",
                    "/**/*.jpg",
                    "/**/*.html",
                    "/**/*.css",
                    "/**/*.js")
                    .permitAll()
                .antMatchers("/api/auth/**")
                    .permitAll()
                .antMatchers("/api/book/**")
                    .permitAll()
                .antMatchers("/api/author/**")
//                        .permitAll()
                    .hasAnyRole("ROLE_ADMIN", "ADMIN", "ROLE_USER", "USER", "ROLE_ROLE_ADMIN", 
"ROLE_ROLE_USER")
            .anyRequest()
            .authenticated();

    http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
UserRepository userRepository;

@Override
@Transactional
public UserDetails loadUserByUsername(String email)
        throws UsernameNotFoundException {
    User user = userRepository.findByEmail(email);

    return UserDetailsImpl.create(user);
}

@Transactional
public UserDetails loadUserById(Integer id) {
    User user = userRepository.findById(id).orElseThrow(
            () -> new UsernameNotFoundException("User not found with id: " + id)
    );

    return UserDetailsImpl.create(user);
}
}
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

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

@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, 
AuthenticationException e) throws IOException, ServletException {
    logger.error("Unauthorized access. Message:", e.getMessage());
    httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
}
}
public class JwtAuthenticationFilter extends OncePerRequestFilter {

@Autowired
private JwtTokenProvider tokenProvider;

@Autowired
private UserDetailsServiceImpl userDetailsService;

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


@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse 
httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
    try {
        String jwt = getJwtFromRequest(httpServletRequest);

        if(StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
            Integer userId = tokenProvider.getUserIdFromJWT(jwt);

            UserDetails userDetails = userDetailsService.loadUserById(userId);
            UsernamePasswordAuthenticationToken authentication = new 
UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

            authentication.setDetails(new 
WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
        }
    } catch (Exception e) {
        logger.error("Could not set user authentication in security context", e);
    }

    filterChain.doFilter(httpServletRequest, httpServletResponse);
}

private String getJwtFromRequest(HttpServletRequest request) {
    String bearerToken = request.getHeader("Authorization");
    if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
        return bearerToken.substring(7, bearerToken.length());
    }
    return null;
}
}
public class UserDetailsImpl implements UserDetails {
private Integer id;

@JsonIgnore
private String email;

private String name;

@JsonIgnore
private String password;

private boolean isAdmin;

private Collection<? extends GrantedAuthority> authorities;

public UserDetailsImpl(Integer id, String email, String name, String 
password, boolean isAdmin, Collection<? extends GrantedAuthority> 
authorities) {
    this.id = id;
    this.name = name;
    this.email = email;
    this.password = password;
    this.authorities = authorities;
    this.isAdmin = isAdmin;
}

public static UserDetailsImpl create(User user) {
    List<GrantedAuthority> authorities = user.getRoles().stream().map(role ->
            new SimpleGrantedAuthority(role.getName().name())
    ).collect(Collectors.toList());

    boolean isAdmin = false;

    for(Role role:  user.getRoles()) {
        if(RoleName.ROLE_ADMIN.equals(role.getName())) {
            isAdmin = true;
        }
    }

    return new UserDetailsImpl(
            user.getId(),
            user.getEmail(),
            user.getName(),
            user.getPassword(),
            isAdmin,
            authorities
    );
}

public Integer getId() {
    return id;
}

public String getName() {
    return name;
}

@Override
public String getUsername() {
    return email;
}

@Override
public String getPassword() {
    return password;
}

public boolean isAdmin() {
    return isAdmin;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return authorities;
}

@Override
public boolean isAccountNonExpired() {
    return true;
}

@Override
public boolean isAccountNonLocked() {
    return true;
}

@Override
public boolean isCredentialsNonExpired() {
    return true;
}

@Override
public boolean isEnabled() {
    return true;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    UserDetailsImpl that = (UserDetailsImpl) o;
    return Objects.equals(id, that.id);
}

@Override
public int hashCode() {

    return Objects.hash(id);
}

共有1个答案

华凯捷
2023-03-14

我看到您没有更新SecurityContextHolder。无法把它放在一个评论,所以我写在这里。

authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest))
SecurityContextHolder.getContext().setAuthentication(authentication); //this seems missing
 类似资料:
  • 我的代码:GoogleCredential凭据 credential.refreshToken() 错误日志: 创建服务号的步骤: 我在凭据中的oauth 2.0中创建了一个Web应用程序 然后我用客户端ID创建了一个服务号 现在我正在使用这个服务号和从它生成的p12证书来验证和创建Google凭据的对象 一旦刷新令牌,我就给了我401例外。 在这种情况下,任何帮助都会受到感激

  • 我想使用爪哇谷歌驱动器API。我尝试了这段代码: 但是我得到了这个错误: 我使用以下配置: 你能告诉我怎么解决这个问题吗?

  • null null 使用NodePort服务公开Keycloak。 应用程序使用istio入口网关公开。 Keycloak服务器版本:9.0.0。

  • 我正在尝试登录基于cloudflare服务器的网站。我使用cloudserver绕过了登录问题,但我的下一个停止点是当我试图发送get请求以访问一些登录后令牌时。 我的代码: 这返回401作为答案: 它的标题是 好的,我首先试着给一个auth。这样地 我再次得到相同的错误,401,但这次响应的头确实有一个www身份验证,我应该质询 根据我所读到的内容,它是基本的意味着我必须在我的头文件中添加一个像

  • Microsoft.Graph REST.API 我试图通过https://graph.microsoft.com/v1.0/me从graph.api获得有关我的信息 我也在这里检查这个其他主题,但我找不到像我一样的错误

  • 我正在使用Maven Jib插件将我的应用程序部署到Gitlab docker注册表。如果我使用并输入用户名和密码,我可以成功登录gitlab注册表。我可以看到