Java 为休息服务构建 Spring 安全拦截器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24902608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 15:28:24  来源:igfitidea点击:

Building a Spring security interceptor for a rest service

javaspringspring-mvcspring-security

提问by bharel

I have a basic REST service exposing various APIs based on Spring MVC and the @RestController mechanism. Now I am trying to add an interceptor for Spring security in order to require login (through a particular REST request) before any other request can be accessed. The idea is that the interceptor checks the active session of the request, and points it to the login service if an active login is not found. If an active login is found the interceptor lets the request through to the proper URL. I've been playing around with the XML files but all I keep getting is redirection loops. :( It's worthwhile noting that I do not have a view associated with this server at all. Access is done via http requests from a GUI that I don't have access to.

我有一个基本的 REST 服务,它基于 Spring MVC 和 @RestController 机制公开各种 API。现在我正在尝试为 Spring 安全性添加一个拦截器,以便在可以访问任何其他请求之前要求登录(通过特定的 REST 请求)。这个想法是拦截器检查请求的活动会话,如果没有找到活动登录,则将其指向登录服务。如果发现活动登录,拦截器会让请求通过正确的 URL。我一直在处理 XML 文件,但我得到的只是重定向循环。:( 值得注意的是,我根本没有与该服务器关联的视图。访问是通过来自我无权访问的 GUI 的 http 请求完成的。

Here's my configuration thus far: Web.xml:

到目前为止,这是我的配置:Web.xml:

    <?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml, /WEB-INF/spring/application-security.xml</param-value>
    </context-param>

    <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>/aisrv/*</url-pattern>
</filter-mapping>

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Processes application requests -->
    <servlet>
        <servlet-name>aisrvServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/aisrvServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>aisrvServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

Servlet-Context.xml

Servlet-Context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="com.bmc.ai.server" />
    <!--- Specific beans for my server -->
</beans:beans>

application-security.xml:

应用程序security.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <http pattern="/resources/**" security="none" />

    <http auto-config="true" use-expressions="true">
   <!--       <intercept-url pattern="/login" access="ROLE_ADMIN" /> -->

  <!--       <intercept-url pattern="/logout" access="permitAll" />
        <intercept-url pattern="/accessdenied" access="permitAll" /> -->

        <intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
<!--          <http-basic /> -->
         <form-login default-target-url="/test"  /> 
   <!--     <logout logout-success-url="/logout" />  -->
    </http>

    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <user name="user" password="123" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

</beans:beans>

I'm sure this is something pretty basic and easy to fix, but I can't seem to find my hand and legs in it. Any help would be greatly appreciated.

我确定这是非常基本且易于修复的东西,但我似乎无法在其中找到我的手和腿。任何帮助将不胜感激。

============EDIT======================= Following the example from Varun I've modified my application-security.xml like this:

============编辑====================== 遵循 Varun 的示例,我修改了我的应用程序安全性。像这样的xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <http pattern="/resources/**" security="none" />

     <http auto-config="true" use-expressions="true">
  <!-- other filters -->
  <custom-filter ref="myCustomFilter" before="SESSION_MANAGEMENT_FILTER" />  
    <intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
</http>


<beans:bean id="myCustomFilter" class="com.company.server.impl.security.RestFilter">

</beans:bean>


<!--     <http auto-config="true" use-expressions="true">
         <intercept-url pattern="/login" access="ROLE_ADMIN" />

        <intercept-url pattern="/logout" access="permitAll" />
        <intercept-url pattern="/accessdenied" access="permitAll" />

        <intercept-url pattern="/**" access="ROLE_USER" requires-channel="https"/>
         <http-basic />
         <form-login default-target-url="/test"  /> 
       <logout logout-success-url="/logout" /> 
    </http>-->

    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <user name="user" password="123" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

</beans:beans>

and added the following RestFiletClass:

并添加了以下 RestFiletClass:

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.filter.GenericFilterBean;

import com.company.server.controller.ExcpetionHandling.GenericErrorExeception;
import com.company.server.interfaces.comm.ICorbaClient;

public class RestFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {

         HttpServletResponse response = ((HttpServletResponse) res);
            HttpServletRequest request = ((HttpServletRequest) req);
            ICorbaClient corba = (ICorbaClient)request.getSession().getAttribute("corba");
            if(corba.getSuccessfulLogin()){
                System.out.println("Authorized through filter");
                chain.doFilter(req, res);
            }else{
                throw new GenericErrorExeception("User unauthorized", null, HttpServletResponse.SC_UNAUTHORIZED);
            }
    }

}

However, spring appears to skip the filter altogether. Do I need to add it somewhere or do something more with it?

但是,spring 似乎完全跳过了过滤器。我是否需要在某处添加它或用它做更多的事情?

采纳答案by Varun Achar

You need to add a custom filter in your spring security xml. In the example below a pre-built filter has been modified, but you can checkout the classes as reference to build your own filter.

您需要在 spring security xml 中添加自定义过滤器。在下面的示例中,一个预先构建的过滤器已被修改,但您可以检出类作为参考以构建您自己的过滤器。

<http use-expressions="true">
  <!-- other filters -->
  <custom-filter ref="myCustomFilter" before="SESSION_MANAGEMENT_FILTER" />  
</http>


<beans:bean id="myCustomFilter" class="com.mycompany.RestFilter">

</beans:bean>

public class RestFilter extends GenericFilterBean {

   // @Override of Filter.doFilter() method
   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
      // Implement
   }
}

Spring security will automatically call this filter before the predefined SESSION_MANAGEMENT_FILTERand run your code.

Spring security 会在预定义之前自动调用此过滤器SESSION_MANAGEMENT_FILTER并运行您的代码。