春天安全“记住我”cookie在第一次请求不可用 [英] Spring security 'remember me' cookie not avaiable in first request

查看:213
本文介绍了春天安全“记住我”cookie在第一次请求不可用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在登录请求后无法检索Spring记住我的cookie,但它在下一个对受保护页面的请求中工作正常。



我在登录请求中设置了记住我的Cookie,但在Spring重定向后无法找回它


  1. 浏览器转到example.com/protected

  2. Spring重定向到登录表单页面

  3. 成功登录后,SPRING_SECURITY_REMEMBER_ME_COOKIE设置在非常精细的自定义子类org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices

  4. 看起来Spring重定向回example.com/protected,whithout往返浏览器,并登录

  5. 我们的org.springframework.security.web.access.expression.WebSecurityExpressionRoot的子类有一些方法,它们是从< ; intercept-url pattern =...access =method()/>

  6. 在我们的方法()request.getCookies

  7. 我们的应用程式有一些问题,因为Cookie遗失了...

到目前为止,我的理论是我不能正确理解SavedRequest。



这里的精简配置:

 < http auto-config =falseuse-expressions =trueauthentication-manager-ref =myAuthenticationManagerpath-type =regex> 
< form-login authentication-success-handler-ref =myAuthenticationSuccessHandlerlogin-page =...login-processing-url =...authentication-failure-url =... username-parameter =usernamepassword-parameter =password/>

< custom-filter ref =logoutFilterposition =LOGOUT_FILTER/>
< expression-handler ref =myWebSecurityExpressionHandler/>

< custom-filter ref =myCustomeFilter1before =FORM_LOGIN_FILTER/>
< custom-filter ref =myCustomeFilter2position =BASIC_AUTH_FILTER/>
< custom-filter ref =mySecurityClientTokenAuthenticationFilterafter =LOGOUT_FILTER/>

< access-denied-handler ref =myAccessDeniedHandler/>
< intercept-url pattern =xxx
access =method()/>

< intercept-url pattern =yyy
access =method()/>
< remember-me services-ref =rememberMeServiceskey =my_remember/>
< / http>

我尝试添加以下内容,唯一的结果是用户没有被重定向到原始页面

 < http ... 
< request-cache ref =nullRequestCache/>
< / http>
< bean:bean id =nullRequestCacheclass =org.springframework.security.web.savedrequest.NullRequestCache/>当在autoLogin()中使用request.getCookie()时,


解决方案

方法,传入的请求是SavedRequestAwareWrapper,它封装了原始请求和保存的请求,并覆盖了getCookies方法。

  @Override 
public Cookie [] getCookies(){
List< Cookie> cookies = savedRequest.getCookies();
return cookie.toArray(new Cookie [cookies.size()]);
}

因此,当你想从请求中获取cookie时, savedRequest。但是,Cookie可能存在于原始请求中。



您可能应该获得获取所需Cookie的原始请求。例如:

  public class ApplicationRememberMeServiceImpl实现RememberMeService,LogoutHandler {

public Authentication autoLogin(HttpServletRequest request, HttpServletResponse响应){

HttpServletRequestWrapper savedRequestWrapper =(HttpServletRequestWrapper)((HttpServletRequestWrapper)request).getRequest();
HttpServletRequest httpServletRequest =(HttpServletRequest)savedRequestWrapper.getRequest();

Cookie cookie = WebUtils.getCookie(httpServletRequest,cookieName);
//逻辑继续...

}

}

更新03/05/2015



因为spring security会多次包装原始的HttpServletRequest,所以提取原始请求更安全方法如下:

  public class ApplicationRememberMeServiceImpl实现RememberMeService,LogoutHandler {

public Authentication autoLogin(HttpServletRequest request ,HttpServletResponse response){

HttpServletRequest httpServletRequest = request;

//从多个包装的HttpServletRequest获取原始请求
if(httpServletRequest instanceof HttpServletRequestWrapper){

HttpServletRequestWrapper httpServletRequestWrapper =(HttpServletRequestWrapper)httpServletRequest;
while(httpServletRequestWrapper.getRequest()instanceof HttpServletRequestWrapper){
httpServletRequestWrapper =(HttpServletRequestWrapper)httpServletRequestWrapper.getRequest();
}

httpServletRequest =(HttpServletRequest)httpServletRequestWrapper.getRequest();

}

Cookie cookie = WebUtils.getCookie(httpServletRequest,cookieName);
//逻辑继续...

}

}


I fail to retrieve the Spring remember me cookie after the login request, but it works fine in the next request to a protected page. Could anyone please tell me how I can get hold of it right away?

I am setting the remember me cookie in the login request, but fail to retrive it after Spring redirects back to the original (protected) url.

Step by step:

  1. Browser goes to example.com/protected
  2. Spring redirects to login form page
  3. Upon successful login, the SPRING_SECURITY_REMEMBER_ME_COOKIE is set in a very thin custom sub class of org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices
  4. It looks like Spring redirects back to example.com/protected, whithout a roundtrip to the browser, and both login "servlet" and protected page is handled by the same thread in Tomcat 6.
  5. Our subclass of org.springframework.security.web.access.expression.WebSecurityExpressionRoot has methods that is invoked from a <intercept-url pattern="..." access="method()" />
  6. In our method() request.getCookies() does not give the remember me cookie on the first request, but on all requests after that.
  7. Our app has some problems because the cookie is missing...

My theory so far is that I don't understand SavedRequest properly.

Condensed config here:

<http auto-config="false" use-expressions="true" authentication-manager-ref="myAuthenticationManager" path-type="regex">
    <form-login authentication-success-handler-ref="myAuthenticationSuccessHandler" login-page="..." login-processing-url="..." authentication-failure-url="..." username-parameter="username" password-parameter="password" />

    <custom-filter ref="logoutFilter" position="LOGOUT_FILTER"/>
    <expression-handler ref="myWebSecurityExpressionHandler" />

    <custom-filter ref="myCustomeFilter1" before="FORM_LOGIN_FILTER"/>
    <custom-filter ref="myCustomeFilter2" position="BASIC_AUTH_FILTER"/>
    <custom-filter ref="mySecurityClientTokenAuthenticationFilter" after="LOGOUT_FILTER" />

    <access-denied-handler ref="myAccessDeniedHandler"/>
    <intercept-url pattern="xxx"
                   access="method()"/>

    <intercept-url pattern="yyy"
                   access="method()"/>
    <remember-me services-ref="rememberMeServices"  key="my_remember"/>
</http>

I tried adding the following, with the only result that the user does not get redirected to the original page.

<http ...
    <request-cache ref="nullRequestCache"/>
</http>
<bean:bean id="nullRequestCache" class="org.springframework.security.web.savedrequest.NullRequestCache"/>

解决方案

When using request.getCookie() in autoLogin() method of RememberMeService, the request passed in is SavedRequestAwareWrapper which encapsulates original request and saved request and overrides the getCookies method.

@Override
public Cookie[] getCookies() {
    List<Cookie> cookies = savedRequest.getCookies();
    return cookies.toArray(new Cookie[cookies.size()]);
}

Therefore, when you want to get cookie from request, you actually get cookie from the savedRequest. However, the cookie may exist in the original request.

You probably should get the original request for getting cookies you want. For example:

public class ApplicationRememberMeServiceImpl implements RememberMeService, LogoutHandler {

    public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {

        HttpServletRequestWrapper savedRequestWrapper = (HttpServletRequestWrapper) ((HttpServletRequestWrapper) request).getRequest();
        HttpServletRequest httpServletRequest = (HttpServletRequest) savedRequestWrapper.getRequest();

        Cookie cookie = WebUtils.getCookie(httpServletRequest, cookieName);
        // logic continues...

    }

}

Update 03/05/2015

Because spring security will wrap the original HttpServletRequest multiple times, it is more safe to extracting the original request in the way below:

public class ApplicationRememberMeServiceImpl implements RememberMeService, LogoutHandler {

    public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {

        HttpServletRequest httpServletRequest = request;

        // Get the original request from multiple wrapped HttpServletRequest
        if(httpServletRequest instanceof HttpServletRequestWrapper) {

            HttpServletRequestWrapper httpServletRequestWrapper = (HttpServletRequestWrapper) httpServletRequest;
            while(httpServletRequestWrapper.getRequest() instanceof HttpServletRequestWrapper) {
                httpServletRequestWrapper = (HttpServletRequestWrapper) httpServletRequestWrapper.getRequest();
            }

            httpServletRequest = (HttpServletRequest) httpServletRequestWrapper.getRequest();

        }

        Cookie cookie = WebUtils.getCookie(httpServletRequest, cookieName);
        // logic continues...

    }

}

这篇关于春天安全“记住我”cookie在第一次请求不可用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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