java - 如何在 spring security 4 xml 配置中禁用特定 url 的安全性以检索访问 token

标签 java xml spring rest security

我开发了一些休息应用程序,并且在配置 Spring Security 时遇到问题。

帮助我在我的其余应用程序中进行 Spring Security 4 的 xml 配置。

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:sec="http://www.springframework.org/schema/security"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
      http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

<import resource="classpath*:securityServicesContext.xml"/>
<import resource="classpath*:businessServicesContext.xml"/>

<sec:http pattern="/rest/**" create-session="stateless" auto-config="false" entry-point-ref="unauthorizedEntryPoint">
    <sec:expression-handler ref="webSecurityExpressionHandler"/>
    <sec:custom-filter ref="customTokenAuthenticationFilter" position="FORM_LOGIN_FILTER"/>
    <sec:intercept-url pattern="/rest/login" access="permitAll"/>
    <sec:intercept-url pattern="/**" access="hasRole('USER')"/>
    <sec:csrf disabled="true"/>
</sec:http>

<sec:authentication-manager id="authenticationManager">
    <sec:authentication-provider ref="daoAuthenticationProvider"/>
</sec:authentication-manager>

<bean id="unauthorizedEntryPoint" class="com.itechart.security.web.security.UnauthorizedEntryPoint"/>

<bean id="customTokenAuthenticationFilter"
      class="com.itechart.security.web.security.CustomTokenAuthenticationFilter">
    <constructor-arg name="defaultFilterProcessesUrl" value="/rest/**"/>
    <constructor-arg name="authenticationManager" ref="authenticationManager"/>
    <constructor-arg name="authenticationSuccessHandler">
        <bean class="com.itechart.security.web.security.TokenSimpleUrlAuthenticationSuccessHandler"/>
    </constructor-arg>
</bean>

当我将用户名和密码发送到/rest/login 时,我在 CustomTokenAuthenticationFilter 中捕获并且身份验证失败。如何将我的 xml 配置为/rest/login 请求不进行过滤,而其他/rest/** 进行过滤?

这是我的 web.xml:

<?xml version="1.0" encoding="UTF-8"?>

http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

<display-name>Security Web Application</display-name>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcherServlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/rest/*</url-pattern>
</filter-mapping>

<resource-ref>
    <res-ref-name>jdbc/SecuritySampleDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

<welcome-file-list>
    <welcome-file>/app/index.html</welcome-file>
</welcome-file-list>

更新1:

public class CustomTokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

private static final Logger logger = LoggerFactory.getLogger(CustomTokenAuthenticationFilter.class);
private String excludedUrl;

public CustomTokenAuthenticationFilter(String excludedUrl, String defaultFilterProcessesUrl, AuthenticationManager authenticationManager, AuthenticationSuccessHandler authenticationSuccessHandler) {
    super(defaultFilterProcessesUrl);
    this.excludedUrl = excludedUrl;
    super.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(defaultFilterProcessesUrl));
    setAuthenticationManager(authenticationManager);
    setAuthenticationSuccessHandler(authenticationSuccessHandler);
}

public final String HEADER_SECURITY_TOKEN = "X-CustomToken";


/**
 * Attempt to authenticate request - basically just pass over to another method to authenticate request headers
 */
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
    String token = request.getHeader(HEADER_SECURITY_TOKEN);
    logger.info("token found:" + token);
    AbstractAuthenticationToken userAuthenticationToken = authUserByToken(token);
    if (userAuthenticationToken == null)
        throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token"));


    return userAuthenticationToken;
}


/**
 * authenticate the user based on token
 *
 * @return
 */
private AbstractAuthenticationToken authUserByToken(String token) {
    if (token == null) {
        return null;
    }
    AbstractAuthenticationToken authToken = null;//todo
    try {
        return authToken;
    } catch (Exception e) {
        logger.error("Authenticate user by token error: ", e);
    }
    return authToken;
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    if (((HttpServletRequest) req).getRequestURI().endsWith(excludedUrl)) {
        chain.doFilter(req, res);
    } else {
        super.doFilter(req, res, chain);
    }
}
}

这是我发送请求时的日志:

21:14:00.805 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/rest/test'; against '/rest/**'
21:14:00.808 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
21:14:00.818 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 2 of 8 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
21:14:00.826 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 3 of 8 in additional filter chain; firing Filter: 'HeaderWriterFilter'
21:14:00.826 [http-nio-8080-exec-1] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@1fd019da
21:14:00.827 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 4 of 8 in additional filter chain; firing Filter: 'CustomTokenAuthenticationFilter'
21:14:00.827 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 5 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
21:14:00.836 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 6 of 8 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
21:14:00.838 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
21:14:00.839 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
21:14:00.839 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
21:14:00.840 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/rest/test'; against '/rest/login'
21:14:00.842 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/rest/test'; against '/rest/test'
21:14:00.842 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /rest/test; Attributes: [permitAll]
21:14:00.843 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
21:14:00.862 [http-nio-8080-exec-1] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@66e0e4e6, returned: 1
21:14:00.862 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
21:14:00.862 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
21:14:00.863 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /rest/test reached end of additional filter chain; proceeding with original chain
21:14:00.925 [http-nio-8080-exec-1] WARN  o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/rest/test] in DispatcherServlet with name 'dispatcherServlet'
21:14:00.933 [http-nio-8080-exec-1] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
21:14:00.933 [http-nio-8080-exec-1] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed

最佳答案

您可以在 customTokenAuthenticationFilter 中添加对 url 的检查,并在目标为 /rest/login 时绕过过滤规则。 考虑这个例子:

    @Override
    protected final void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException,
                    IOException {
        if (!request.getRequestURL().toString().endsWith("rest/login")) { 
            ... apply filtering logic...
        }
        filterChain.doFilter(request, response);
    }

关于java - 如何在 spring security 4 xml 配置中禁用特定 url 的安全性以检索访问 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35381408/

相关文章:

java - 没有@Id的 hibernate/持久性

java - 检测套接字是否有错误的IP并且无法连接

java - 如何从 FHIR 资源生成 Java 模型类?

xml - 编辑xml文件后如何保留重音符号?

java - 如何在没有嵌入式 tomcat 的情况下启动 Spring Boot 应用程序?

java - 如何对java代码进行单元测试

java - 在 Java 中比较字符串

javascript - 在 JavaScript 函数中解析同级文件夹

java - Spring Data Elasticsearch - 找不到能够从类型 [java.lang.Long] 转换为类型 [java.time.Instant] 的转换器

java - 无法使用 spring javamail 从服务器 heroku 发送电子邮件