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

带有JWT/antMatchers阻止访问的Spring Security配置

尚河
2023-03-14

我们正在1.3Spring Boot应用程序中设置Spring Security性。我们已经创建了一个类来使用Java配置来配置所有内容,但是出于某种原因,每当我试图访问任何配置为“permitall()”的URL时,我都会得到一个类似于下面这样的消息响应:

{
  "timestamp": 1443099232454,
  "status": 403,
  "error": "Forbidden",
  "message": "Access Denied",
  "path": "/api/register"
}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Inject
    private Http401UnauthorizedEntryPoint authenticationEntryPoint;

    @Inject
    private UserDetailsService userDetailsService;

    @Inject
    private TokenProvider tokenProvider;

    public SecurityConfig() {
        super(true);
    }

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

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .exceptionHandling()
            .authenticationEntryPoint(authenticationEntryPoint)
        .and()
            .csrf()
            .disable()
            .headers()
            .frameOptions()
            .disable()
        .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
            .authorizeRequests()
            .antMatchers("/api/register").permitAll()
            .antMatchers("/api/activate").permitAll()
            .antMatchers("/api/authenticate").permitAll()
        .and()
            .authorizeRequests()
            .anyRequest()
            .authenticated()
        .and()
            .apply(securityConfigurerAdapter());
        // @formatter:on
    }

    private JwtTokenConfigurer securityConfigurerAdapter() {
        return new JwtTokenConfigurer(tokenProvider);
    }
}
@Service("userDetailsService")
@Log4j2
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {

    @Inject
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(final String email) {
        log.debug("Authenticating {}", email);
        String lowercaseEmail = email.toLowerCase();
        Optional<User> userFromDatabase = userRepository.findOneByEmail(lowercaseEmail);
        return userFromDatabase.map(
                user -> {
                    if (!user.isEnabled()) {
                        throw new DisabledException("User " + lowercaseEmail + " is disabled");
                    }

                    List<GrantedAuthority> grantedAuthorities = user.getRoles().stream()
                            .map(role -> role.getGrantedAuthority()).collect(Collectors.toList());

                    return new org.springframework.security.core.userdetails.User(lowercaseEmail, user.getPassword(),
                        grantedAuthorities);
                }).orElseThrow(
                () -> new UsernameNotFoundException("User " + lowercaseEmail + " was not found in the database"));
    }
}
public class JwtTokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

    private TokenProvider tokenProvider;

    public JwtTokenConfigurer(TokenProvider tokenProvider) {
        this.tokenProvider = tokenProvider;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        JwtTokenFilter customFilter = new JwtTokenFilter(tokenProvider);
        http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
public class JwtTokenFilter extends GenericFilterBean {
    private final static String JWT_TOKEN_HEADER_NAME = "Authorization";
    private TokenProvider tokenProvider;

    public JwtTokenFilter(TokenProvider tokenProvider) {
        this.tokenProvider = tokenProvider;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {
        try {
            HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
            String jwtToken = httpServletRequest.getHeader(JWT_TOKEN_HEADER_NAME);

            if (StringUtils.hasText(jwtToken)) {
                String authorizationSchema = "Bearer";
                if (jwtToken.indexOf(authorizationSchema) == -1) {
                    throw new InsufficientAuthenticationException("Authorization schema not found");
                }
                jwtToken = jwtToken.substring(authorizationSchema.length()).trim();

                JwtClaims claims = tokenProvider.parseToken(jwtToken);
                String email = (String) claims.getClaimValue(TokenConstants.EMAIL.name());
                List<GrantedAuthority> grantedAuthorities = claims.getStringListClaimValue(TokenConstants.ROLES.name())
                    .stream().map(role -> new SimpleGrantedAuthority(role)).collect(Collectors.toList());

                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                    email, null, grantedAuthorities);
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
            filterChain.doFilter(servletRequest, servletResponse);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}
@Component
public class Http401UnauthorizedEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2)
        throws IOException, ServletException {
        log.debug("Pre-authenticated entry point called. Rejecting access");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied");
    }
}
.antMatchers("/api/register").permitAll()
.antMatchers("/api/activate").permitAll()
.antMatchers("/api/authenticate").permitAll()

我被拒绝...有什么想法吗?

共有1个答案

年烈
2023-03-14

您需要允许匿名用户。

@Override
protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http
        .exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint)
    .and()
        .csrf()
        .disable()
        .headers()
        .frameOptions()
        .disable()
    .and()
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()
        .authorizeRequests()
        .antMatchers("/api/register").permitAll()
        .antMatchers("/api/activate").permitAll()
        .antMatchers("/api/authenticate").permitAll()
    .and()
        .anonymous()
        .authorizeRequests()
        .anyRequest()
        .authenticated()
    .and()
        .apply(securityConfigurerAdapter());
    // @formatter:on
}

因为AbstractSecurityInterceptor总是询问SecurityContexTholder中是否有内容。AbstractSecurityInterceptor#BeForeInvocation第221行

if (SecurityContextHolder.getContext().getAuthentication() == null) {
 credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound","An Authentication object was not found in the SecurityContext"),object, attributes);

}
 类似资料:
  • 我正试图从vue.js端访问laravel服务器。但它表明 CORS策略阻止从来源“http://localhost:8000/api/registerdoctor”访问位于“http://localhost:8080”的XMLHttpRequest:请求的资源上没有“Access-Control-Allow-Origin”标头。 怎么办?

  • 我正在使用spring-boot 2.3.9和spring-security以及keycloak 12.0.4。 和我的服务bean创建配置 编辑:这可能与Spring-Cloud-Starter-Sleuth有关。如果我移除这个依赖关系,所有的事情就会像预期的那样工作。但我也需要侦探。

  • 问题内容: 我正在尝试使用ServiceStackRedis客户端实现我认为是非常常见的缓存方案,但是我很难找到一个很好的例子。 在ASP.NETMVC应用程序中,我们对外部Web服务进行了相对长时间的运行(按计量),并将结果缓存了一段时间。在高速缓存实现中,希望阻止对该键的其他请求,直到Web服务调用完成为止,以避免其他(昂贵)调用。 那么,实现键级锁定的最佳方法是什么?Redis开箱即用吗?S

  • 我正在与Django合作一个项目,该项目通过React前端上的Django Rest框架通过API提供数据。可浏览的API工作正常,但是,react前端在控制台中给出了一个错误。 我已成功安装django cors标头。 CORS策略阻止从http://127.0.0.1:8000/products/http://localhost:3000获取数据:请求的资源上不存在访问控制允许来源标头。如果不

  • 我正在使用以下版本 null CORS策略阻止了从原点获取的访问:请求的资源上没有'Access->Control-Allow-Origin'标头。如果一个不透明的响应满足您的需要,请将请求的模式设置为“no-cors”,以便在禁用CORS的情况下获取资源。 我不明白为什么我会得到这个错误。 以下是从Google Chrome开发者工具中提取的相关请求和响应细节 推荐人策略:严格的-原产地-当-跨

  • 问题内容: 我想阻止从外部直接访问docker容器。我使用haproxy,并且只希望访问端口80、443。 我在iptables中添加了以下规则。但是我仍然可以通过不同的端口访问Docker容器。 这可能是由于DOCKER链 我需要创建什么规则来阻止直接访问? 问题答案: 您可以使用命令创建一个网络来连接应用程序和代理,而不必使用IP表来执行此操作。另外,请勿在任何端口上公开应用程序。您应该公开的