Spring Security具有antMatchers子模式的多个antMatchers

时间:2019-10-25 14:38:55

标签: spring authentication spring-security jwt

我在link

中为Spring Security进行了配置
http
    .requestMatchers()
        .antMatchers("/web/**")
        .and()
    .authorizeRequests()
        .antMatchers("/web/initial/**").permitAll()
        .antMatchers("/**").authenticated()
        .and()
    .addFilterBefore(jwtauthFilter, UsernamePasswordAuthenticationFilter.class);

http
    .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.NEVER);

目前,我总是收到403,这意味着它已通过过滤器进行了身份验证。 在这里,我需要过滤/web/**模式之外的所有到达/web/initial/**的请求。有什么方法可以实现这一目标,还是必须将/web/initial/**更改为不在网络下的其他模式? 我已经引用了此link,但此处没有使用requestMatchers()

DEBUG: org.springframework.security.web.util.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/web/**']
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/web/initial/'; against '/web/**'
DEBUG: org.springframework.security.web.util.matcher.OrRequestMatcher - matched
DEBUG: org.springframework.security.web.FilterChainProxy - /web/initial/ at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /web/initial/ at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@a8d3a7a2: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@a8d3a7a2: Principal: com.leadwinner.gpms.user.entities.EmployeeEntity@572c5866; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 192.168.0.17; SessionId: 75ADFD778EFFEE25FB2F3020E8043DB5; Not granted any authorities'
DEBUG: org.springframework.security.web.FilterChainProxy - /web/initial/ at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
DEBUG: org.springframework.security.web.FilterChainProxy - /web/initial/ at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
DEBUG: org.springframework.security.web.util.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', GET]
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/web/initial/'; against '/logout'
DEBUG: org.springframework.security.web.util.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', POST]
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /web/initial/' doesn't match 'POST /logout
DEBUG: org.springframework.security.web.util.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', PUT]
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /web/initial/' doesn't match 'PUT /logout
DEBUG: org.springframework.security.web.util.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', DELETE]
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /web/initial/' doesn't match 'DELETE /logout
DEBUG: org.springframework.security.web.util.matcher.OrRequestMatcher - No matches found
DEBUG: org.springframework.security.web.FilterChainProxy - /web/initial/ at position 5 of 11 in additional filter chain; firing Filter: 'JwtAuthenticationTokenFilter'
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Request URL/gpms/web/initial/
DEBUG: org.springframework.security.web.header.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@67494a33
DEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed


JwtAuthenticationFilter

package com.leadwinner.sms.config.jwt;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import com.leadwinner.sms.CustomExceptionHandler;
import com.leadwinner.sms.SessionInfo;

import io.jsonwebtoken.ExpiredJwtException;
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private CustomExceptionHandler customExceptionHandler;

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Autowired
    private SessionInfo sessionInfo;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        final String header = request.getHeader("Authorization");
        if (header != null && header.startsWith("Bearer ")) {
            String authToken = header.substring(7);

            try {
                String username = jwtTokenUtil.getUsernameFromToken(authToken);

                if (username != null && SecurityContextHolder.getContext().getAuthentication() == null
                        && username.equals(sessionInfo.getBaseEmployeeId())) {
                    if (jwtTokenUtil.validateToken(authToken, username)
                            && username.equals(sessionInfo.getBaseEmployeeId())) {
                        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = 
                                new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
                        usernamePasswordAuthenticationToken
                                .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                    }
                }
                chain.doFilter(request, response);
            } catch (ExpiredJwtException e) {
                System.out.println("Unable to get JWT Token, possibly expired");
                customExceptionHandler.jwtTokenAuthFailedException(request, response, e);
                redirectStrategy.sendRedirect(request, response, "/login");
            } catch (Exception e) {
                redirectStrategy.sendRedirect(request, response, "/login");
                System.out.println("Other exception");
            }
        }
    }

    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }

    protected RedirectStrategy getRedirectStrategy() {
        return redirectStrategy;
    }
}

1 个答案:

答案 0 :(得分:0)

在您的配置中,/web/initial/**不会得到403

您的配置是

.antMatchers("/web/initial/**").permitAll()
.antMatchers("/**").authenticated()

这里FilterSecurityInterceptor尝试匹配
请求的URL的PathWithinApplication 反对 已配置ant模式 按配置顺序排列(先匹配匹配)

.antMatchers("/web/initial/**").permitAll()首先是赢家。

出现/web/initial/**的问题403(禁止)。检查您的jwtauthFilter逻辑。


示例说明,以证明第一个匹配的antMatcher获胜 "/app/admin/**"需要ROLE_ADMIN,但首先需要/app/admin/app-config

http
    .authorizeRequests()
        .antMatchers("/resources/**", "/", "/login", "/api/**").permitAll()
        .antMatchers("/app/admin/app-config").permitAll()
        .antMatchers("/app/admin/**").hasRole("ADMIN")
        .antMatchers("/app/user/**").hasAnyRole("ADMIN", "USER")

未经登录(未经身份验证的用户)而请求http://localhost:8080/sec-project/app/admin/app-config的请求将导致以下日志,您会注意到匹配并使用了allowAll属性,并为未经身份验证的用户授予了ROLE_ANONYMOUS

DEBUG - /app/admin/app-config at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 
DEBUG - Checking match of request : '/app/admin/app-config'; against '/resources/**' 
DEBUG - Checking match of request : '/app/admin/app-config'; against '/' 
DEBUG - Checking match of request : '/app/admin/app-config'; against '/login' 
DEBUG - Checking match of request : '/app/admin/app-config'; against '/api/**' 
DEBUG - Checking match of request : '/app/admin/app-config'; against '/app/admin/app-config' 
DEBUG - Secure object: FilterInvocation: URL: /app/admin/app-config; Attributes: [permitAll] 
DEBUG - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@511cd205: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@2cd90: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 696171A944493ACA1A0F7D560D93D42B; Granted Authorities: ROLE_ANONYMOUS 
DEBUG - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@6df827bf, returned: 1 
DEBUG - Authorization successful