简体   繁体   English

Spring Security登录/注销问题

[英]Spring Security login/logout problems

I am using Spring 4.3.3 and I am trying to implement login/logout functionalities for my application. 我正在使用Spring 4.3.3,并且正在尝试为我的应用程序实现登录/注销功能。 The issue I am having is that if I log in and log back out again straight away all works as expected. 我遇到的问题是,如果我登录并再次注销后,所有工作都可以按预期进行。 I am taken to the login page at URL:login?logout with a successfully logged out message in the login box. 我被带到URL:login?logout的登录页面,并在登录框中输入了成功注销的消息。 However, if I login and navigate to another page then logout I am again correctly taken to the login page with a successfully logged out message in the login box, but when I click login I am not logged in. Instead I an taken to the login with URL: login with no message and I need to click login a second time to be logged in. Below is some of the code I am using 但是,如果我登录并导航到另一个页面然后注销,则我将再次正确进入带登录框的成功注销消息的登录页面,但是当我单击“登录”时,我却没有登录。使用URL:无消息登录,我需要再次单击登录才能登录。以下是我正在使用的一些代码

security.xml security.xml文件

<http pattern="/resources/**" security="none"/>
<http pattern="/forgot**" security="none"/>
<http pattern="/reset**" security="none" />
<!-- enable use-expressions -->
<security:http 
    auto-config="false" 
    use-expressions="true">
    <headers><cache-control/></headers>
    <security:intercept-url pattern="/resources**" access="permitAll" />
    <security:intercept-url pattern="/login**" access="permitAll" />
    <security:intercept-url pattern="/users**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
    <security:intercept-url pattern="/suppliers**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
    <security:intercept-url pattern="/reports**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
    <security:intercept-url pattern="/games**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
    <security:intercept-url pattern="/clients**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
    <security:intercept-url pattern="/servers**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
    <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>
    <security:intercept-url pattern="/logs**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>

<!-- access denied page -->
    <access-denied-handler error-page="/403" />
    <security:form-login 
        login-page="/login" 
        authentication-failure-url="/login?error" 

        username-parameter="username"
        password-parameter="password" 
        login-processing-url="/auth/login_check" />

    <security:logout 
        invalidate-session="true"
        logout-success-url="/login"
        logout-url="/login?logout"
        delete-cookies="JSESSIONID"/>
    <!-- enable csrf protection -->
    <csrf/>
    <!-- Default lifeTime 2 weeks can be configured -->
    <!--<remember-me key="uniqueAndSecret"/>-->
</security:http>

Controller Method 控制器方式

@RequestMapping(value = "/login", method = RequestMethod.GET)
public @ResponseBody ModelAndView login( @RequestParam(value = "error", required = false) String error, @RequestParam(value = "logout", required = false) String logout, HttpServletResponse response, HttpServletRequest request, SessionStatus sessionStatus) throws IOException {

    ModelAndView model = new ModelAndView();

    if (error != null) {
        model.addObject("error", getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION"));
    }

    if (logout != null) {

        HttpSession session= request.getSession(false);

        SecurityContextHolder.clearContext();
        session= request.getSession(false);

        if(session != null) {
            session.invalidate();
        }

        for(Cookie cookie : request.getCookies()) {
                cookie.setMaxAge(0);
        }

        //sessionStatus.setComplete();
        //request.getSession(false).invalidate();

        model.addObject("msg", "You've been logged out successfully.");
    }
    model.setViewName("login");
    return model;

}

login.jsp login.jsp的

<form name='loginForm' action="<c:url value='/auth/login_check?targetUrl=${targetUrl}' />" method='POST'>
        <div class="form-group">
            <div id="emailError" class="alert alert-danger" style="display:none;"></div> 
            <label for="email">Email
                <input  class="form-control" id="email" type="email" name="username" placeholder="Email">
            </label> 
        </div>
        <div class="form-group">
            <label for="password">Password
                <input class="form-control" id="password" type="password" name="password" placeholder="Password">
            </label>
        </div>
            Remember Me: <input type="checkbox" name="remember-me" />
            <input id="login"class="btn btn-primary" name="submit" type="submit" value="Login">
            <div><a id="forgotPass">forgot password</a></div>
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    </form>

Judging from your security configuration, I'm not sure if you're using the CookieCsrfTokenRepository or not. 从您的安全配置来看,我不确定您是否正在使用CookieCsrfTokenRepository I see you're manually expiring all cookies when logging out: 我看到您在注销时手动使所有cookie过期:

 for(Cookie cookie : request.getCookies()) {
     cookie.setMaxAge(0);
 }

Unless you have other cookies you manually set in your application, the session cookie will be deleted by default, since you configured it to do so: 除非您在应用程序中手动设置了其他cookie,否则默认情况下会删除会话cookie,因为您已将其配置为:

<security:logout 
    ...
    delete-cookies="JSESSIONID"/>

My guess is that you're also clearing the CSRF token cookie, so the login-page that gets rendered without the token. 我的猜测是,您还要清除CSRF令牌Cookie,因此无需令牌即可呈现的登录页面。 Submitting the form may fail silently due to mismatch of CSRF, taking you back to the login page. 由于CSRF的不匹配,提交表单可能会在无提示的情况下失败,从而使您返回登录页面。 This time, the CSRF value will be set again and subsequent login attempt succeeds. 这次,将再次设置CSRF值,并且随后的登录尝试成功。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM