使用 Spring 3 在 REST 中登录/注销 [英] Login/logout in REST with Spring 3

查看:18
本文介绍了使用 Spring 3 在 REST 中登录/注销的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在用 Spring 3 开发 RESTful webservices,我们需要有登录/注销的功能,比如 /webservices/login///>/webservices/注销.会话应存储在上下文中,直到会话超时或注销以允许使用其他 Web 服务.任何访问没有会话信息的网络服务的请求都应该被拒绝.正在为这种情况寻找最先进的解决方案.

We are developing RESTful webservices with Spring 3 and we need to have the functionality of login/logout, something like /webservices/login/<username>/<password>/ and /webservices/logout. The session should be stored in the context until the session is timed out or logged out to allow consumption of other webservices. Any request to access webservices without session information should be rejected. Looking for state-of-the-art solution for this scenario.

我实际上是在重新提出这里提出的问题Spring Security 3 以编程方式登录,但仍然没有正确回答.请同时在 web.xml 中指定所需的更改.

I am actually resurrecting the question asked here Spring Security 3 programmatically login, which is still not properly answered. Please specify the changes needed in web.xml as well.

推荐答案

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

I would suggest defining your Spring Security filters completely manually. It's not that difficult, and you get full control over your login/logout behaviour.

首先,您将需要标准的 web.xml 简介将过滤器链处理委托给 Spring(如果您使用的不是 Servlet API 版本 3,则删除异步支持):

First of all, you will need standard web.xml blurb to delegate filter chain handling to Spring (remove async-supported if you are not on Servlet API ver 3):

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



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

现在,在安全上下文中,您将为每个路径分别定义过滤器.过滤器可以验证用户、注销用户、检查安全凭证等.

Now, in security context you will define filters separately for each path. Filters can authenticate user, log out user, check security credentials etc.

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <sec:filter-chain-map path-type="ant">
        <sec:filter-chain pattern="/login" filters="sif,wsFilter"/>
        <sec:filter-chain pattern="/logout" filters="sif,logoutFilter" />
        <sec:filter-chain pattern="/rest/**" filters="sif,fsi"/>
    </sec:filter-chain-map>
</bean>

上面的 XML 告诉 Spring 通过过滤器链将请求传递给特定的上下文相关 URL.任何过滤器链中的第一件事是建立安全上下文 - 'sif' bean 负责.

The XML above tells Spring to pass requests to specific context-relative URLs through filter chains. First thing in any of the filter chains is establishing security context - 'sif' bean takes care of that.

<bean id="sif" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>

链中的下一个过滤器现在可以将数据添加到安全上下文(读取:登录/注销用户),或者根据所述安全上下文决定是否允许访问.

Next filter in chain can now either add data to the security context (read: log in/log out user), or make a decision as to whether allow access based on said security context.

对于您的登录 URL,您需要一个过滤器,从请求中读取身份验证数据,对其进行验证,然后将其存储在安全上下文中(存储在会话中):

For your login URL you will want a filter that reads authentication data from the request, validates it, and in turn stores it in security context (which is stored in session):

<bean id="wsFilter" class="my.own.security.AuthenticationFilter">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="authenticationSuccessHandler" ref="myAuthSuccessHandler"/>
  <property name="passwordParameter" value="pass"></property>
  <property name="usernameParameter" value="user"></property>
  <property name="postOnly" value="false"></property>

您可以使用 Spring 通用 UsernamePasswordAuthenticationFilter 但我使用我自己的实现的原因是继续过滤器链处理(默认实现假设用户将在成功验证时重定向并终止过滤器链),并且能够每次将用户名和密码传递给它时处理身份验证:

You can use Spring generic UsernamePasswordAuthenticationFilter but the reason I use my own implementation is to continue filter chain processing (default implementation assumes user will get redirected on successful auth and terminates filter chain), and being able to process authentication every time username and password is passed to it:

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);
}

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

You can add any number of your own filter implementations for /login path, such as authentication using HTTP basic auth header, digest header, or even extract username/pwd from the request body. Spring provides a bunch of filters for that.

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

I have my own auth success handler who overrides the default redirect strategy:

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,请查看文档)

You don't have to have custom auth success handler (and probably custom auth filter as well) if you're ok with user being redirected after successful login (redirect URL can be customized, check docs)

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

Define authentication manager who will be responsible for retrieving user's details:

<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 实现.

You will have to provide your own user details bean implementation here.

Logout filter:负责清除安全上下文

Logout filter: responsible for clearing security context

<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"/>

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

Access control filter (should be self-explanatory):

<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>

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

You should also be able to secure your REST services with @Secured annotations on methods.

上面的上下文是从现有的 REST 服务 webapp 中提取的 - 对于任何可能的错别字,抱歉.

Context above was plucked from existing REST service webapp - sorry for any possible typos.

通过使用常用的 sec Spring 标签,也可以至少完成此处实现的大部分内容,但我更喜欢自定义方法,因为这给了我最大的控制权.

It is also possible to do at least most of what is implemented here by using stock sec Spring tags, but I prefer custom approach as that gives me most control.

希望这至少能让你开始.

Hope this at least gets you started.

这篇关于使用 Spring 3 在 REST 中登录/注销的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆