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

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

问题描述

我们正在使用Spring 3开发RESTful Web服务,我们需要具有登录/注销功能,例如/webservices/login/<username>/<password>//webservices/logout.会话应存储在上下文中,直到会话超时或注销以允许使用其他Web服务.没有会话信息的任何访问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 blurb来将过滤器链处理委托给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基本auth标头,摘要标头进行身份验证,甚至从请求正文中提取用户名/pwd. 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: 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天全站免登陆