Spring Security註銷登錄實例

這篇教程文章將向您展示如何以編程方式註銷 Spring Security 用戶。使用瀏覽器的後退按鈕也能很好顯示。要整個工程完成代碼編寫並運行後,主頁面如下圖所示 -
Spring

首先我們先來看看工程結構,這裏使用的是註釋方式來實現的。如下圖中所示 - 

Spring

一般情況下,在你的視圖中應該提供一個簡單的註銷鏈接來註銷用戶,類似如下所示: 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

Admin page Dear ${user}, Welcome to Admin Page. ">Logout  

沒有什麼特別的東西。現在,我們只需要在映射控制器到  /logout 註銷鏈接。創建一個新的方法如下所示: 

@RequestMapping(value="/logout", method = RequestMethod.GET)
public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null){    
        new SecurityContextLogoutHandler().logout(request, response, auth);
    }
    return "redirect:/login?logout";//You can redirect wherever you want, but generally it's a good practice to show login screen again.
}

 

在這裏,首先我們確定,如果用戶在認證之後使用 SecurityContextHolder.getContext().getAuthentication() 。如果是這樣,那麼我們調用 SecurityContextLogoutHandler().logout(request, response, auth) 註銷用戶。 

註銷調用執行以下操作:

  • HTTP的會話失效,那麼解除綁定到它的任何對象;

  • 將刪除 SecurityContext 的身份驗證,以防止併發請求的問題;

  • 顯式地清除當前線程上下文值;

就這樣,不需要在應用程序中的任何其他地方處理註銷。請注意,你甚至不需要做任何特殊的Spring配置(XML或基於註釋),信息如下圖所示:

package com.yiibai.springsecurity.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("yiibai").password("123456").roles("USER");
    auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
    auth.inMemoryAuthentication().withUser("dba").password("123456").roles("ADMIN","DBA");
}

@Override
protected void configure(HttpSecurity http) throws Exception {

  http.authorizeRequests()
      .antMatchers("/", "/home").permitAll()
      .antMatchers("/admin/\*\*").access("hasRole('ADMIN')")
      .antMatchers("/db/\*\*").access("hasRole('ADMIN') and hasRole('DBA')")
      .and().formLogin().loginPage("/login")
      .usernameParameter("ssoId").passwordParameter("password")
      .and().exceptionHandling().accessDeniedPage("/Access\_Denied");
}

}

如在上面提到的,沒有特殊配置來處理註銷。

以上如果使用 XML 來配置 Security ,那麼格式如下:

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">

<http auto-config="true" >
    <intercept-url pattern="/" access="hasRole('USER')" />
    <intercept-url pattern="/home" access="hasRole('USER')" />
    <intercept-url pattern="/admin\*\*" access="hasRole('ADMIN')" />
    <intercept-url pattern="/dba\*\*" access="hasRole('ADMIN') and hasRole('DBA')" />
    <form-login  login-page="/login" 
                 username-parameter="ssoId" 
                 password-parameter="password" 
                 authentication-failure-url="/Access\_Denied" />
</http>

<authentication-manager >
    <authentication-provider>
        <user-service>
            <user name="yiibai"  password="123456"  authorities="ROLE\_USER" />
            <user name="admin" password="123456" authorities="ROLE\_ADMIN" />
            <user name="dba"   password="123456" authorities="ROLE\_ADMIN,ROLE\_DBA" />
        </user-service>
    </authentication-provider>
</authentication-manager>

在本系列教程中的應用程序代碼,在之後的文章都是基於這個教程的。所以如果打算往後學習其它教程,請務必清楚理解此文章代碼和邏輯,以及相關配置或原理。

發佈並運行

如需要自己動手實踐,可在文章底部提供的下載鏈接並點擊下載本示例代碼,這個項目的完整代碼。它是在Servlet 3.0的容器(Tomcat7/8,本文章使用 Tomcat7)上構建和部署運行的。

打開您的瀏覽器,在地址欄中輸入網址: http://localhost:8080/SpringSecurityCustomLogout/ ,默認的頁面將顯示如下 - 
Spring

現在訪問  http://localhost:8080/SpringSecurityCustomLogout/admin,系統將提示您登錄,如下圖中所示 - 
Spring

提供用戶名和密碼(admin/123456)並點擊提交,就會看到管理頁面。如下圖中所示 -
Spring

點擊註銷,將會自動跳轉到登錄頁。如下圖中所示 - 
Spring

點擊瀏覽器後退按鈕,將會留在登錄屏幕。如下所示 -
Spring

而已。下一篇文章將學習如何顯示基於已登錄用戶的角色,使用Spring Security  標籤顯示 JSP/視圖等等。

下載源代碼

05-SpringSecurityCustomLogout.zip