使用Spring3在REST中登录/注销

使用Spring3在REST中登录/注销,spring,rest,spring-security,spring-webflow,spring-3,Spring,Rest,Spring Security,Spring Webflow,Spring 3,我们正在用Spring 3开发RESTful Web服务,我们需要具有登录/注销功能,类似于/webservices/login//和/webservices/logout。会话应存储在上下文中,直到会话超时或注销以允许使用其他Web服务为止。任何访问没有会话信息的Web服务的请求都应该被拒绝。正在为此场景寻找最先进的解决方案 我实际上是在重复这里提出的问题,这个问题仍然没有得到正确的回答。请在web.xml中指定所需的更改。我建议完全手动定义Spring安全过滤器。这并不难,您可以完全控制您的

我们正在用Spring 3开发RESTful Web服务,我们需要具有登录/注销功能,类似于
/webservices/login//
/webservices/logout
。会话应存储在上下文中,直到会话超时或注销以允许使用其他Web服务为止。任何访问没有会话信息的Web服务的请求都应该被拒绝。正在为此场景寻找最先进的解决方案


我实际上是在重复这里提出的问题,这个问题仍然没有得到正确的回答。请在web.xml中指定所需的更改。

我建议完全手动定义Spring安全过滤器。这并不难,您可以完全控制您的登录/注销行为

首先,您需要标准的web.xml blurb来将过滤器链处理委托给Spring(如果您不在Servlet API版本3上,请删除支持的异步):

您可以为/login路径添加任意数量的您自己的过滤器实现,例如使用HTTP基本身份验证标头、摘要标头进行身份验证,甚至从请求正文中提取用户名/pwd。Spring为此提供了一系列过滤器

我有自己的身份验证成功处理程序,它覆盖默认重定向策略:

public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

   @PostConstruct
   public void afterPropertiesSet() {
       setRedirectStrategy(new NoRedirectStrategy());
   }

    protected class NoRedirectStrategy implements RedirectStrategy {

        @Override
        public void sendRedirect(HttpServletRequest request,
                HttpServletResponse response, String url) throws IOException {
            // no redirect

        }

    }

}
如果您同意在成功登录后重定向用户(可以自定义重定向URL,请检查文档),则不必使用自定义身份验证成功处理程序(可能还需要自定义身份验证筛选器)

定义将负责检索用户详细信息的身份验证管理员:

<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="myAuthAuthProvider"/>
</sec:authentication-manager>

 <bean id="myAuthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService">
        <bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
            <property name="userDetailsService" ref="myUserDetailsImpl"/>
        </bean>
    </property>
</bean>

您必须在这里提供自己的用户详细信息bean实现

注销筛选器:负责清除安全上下文

<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
        </list>
    </constructor-arg>
</bean>

通用身份验证工具:

<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <property name="allowIfAllAbstainDecisions" value="false"/>
    <property name="decisionVoters">
        <list>
            <ref bean="roleVoter"/>
        </list>
    </property>
</bean>

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>

<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>

访问控制过滤器(应该是不言自明的):


您还应该能够使用方法上的
@Secured
注释来保护REST服务

上面的上下文是从现有的REST服务webapp中提取的-对于任何可能的拼写错误,我深表歉意

通过使用stock
sec
Spring标记,也可以至少完成这里实现的大部分工作,但我更喜欢自定义方法,因为这样可以提供最多的控制


希望这至少能让你开始。

我强烈建议你不要在URL中输入密码甚至用户名。这些由中介机构记录,存储在历史记录中,等等。相反,您使用一种现有的机制,如HTTP基本身份验证(当然是通过SSL)。这就是“RESTful”方式:使用HTTP的本机功能。(我不能谈论Spring安全性的用法。)看看这篇文章,它描述了如何使用标准Spring安全性轻松配置REST和常规身份验证。非常感谢您给出了这个令人信服且详细的答案。您将如何调用注销URL来注销用户?@Franklin,请注意springSecurityFilterChain bean上的路径定义:path/Logout设置为调用logoutFilter,这将清除安全上下文,并注销关于spring sec flow Controll的用户最佳答案—非常好而且详细的答案。至于注销-我做的有点不同,我认为值得一看:
public class MyAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
    return ( StringUtils.hasText(obtainUsername(request)) && StringUtils.hasText(obtainPassword(request)) );
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
        Authentication authResult) throws IOException, ServletException{
    super.successfulAuthentication(request, response, chain, authResult);
    chain.doFilter(request, response);
}
public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

   @PostConstruct
   public void afterPropertiesSet() {
       setRedirectStrategy(new NoRedirectStrategy());
   }

    protected class NoRedirectStrategy implements RedirectStrategy {

        @Override
        public void sendRedirect(HttpServletRequest request,
                HttpServletResponse response, String url) throws IOException {
            // no redirect

        }

    }

}
<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="myAuthAuthProvider"/>
</sec:authentication-manager>

 <bean id="myAuthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService">
        <bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
            <property name="userDetailsService" ref="myUserDetailsImpl"/>
        </bean>
    </property>
</bean>
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
        </list>
    </constructor-arg>
</bean>
<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <property name="allowIfAllAbstainDecisions" value="false"/>
    <property name="decisionVoters">
        <list>
            <ref bean="roleVoter"/>
        </list>
    </property>
</bean>

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>

<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>
<bean id="fsi" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <property name="authenticationManager" ref="myAuthenticationManager"/>
    <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
    <property name="securityMetadataSource">
        <sec:filter-invocation-definition-source>
            <sec:intercept-url pattern="/rest/**" access="ROLE_REST"/>
        </sec:filter-invocation-definition-source>
    </property>
</bean>