这篇教程文章将向您展示如何以编程方式注销 Spring Security 用户。使用浏览器的后退按钮也能很好显示。要整个工程完成代码编写并运行后,主页面如下图所示 -
首先我们先来看看工程结构,这里使用的是注释方式来实现的。如下图中所示 -
一般情况下,在你的视图中应该提供一个简单的注销链接来注销用户,类似如下所示:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Admin page</title> </head> <body> Dear <strong>${user}</strong>, Welcome to Admin Page. <a href="<c:url value="/logout" />">Logout</a> </body> </html>
没有什么特别的东西。现在,我们只需要在映射控制器到 /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> </beans:beans>
在本系列教程中的应用程序代码,在之后的文章都是基于这个教程的。所以如果打算往后学习其它教程,请务必清楚理解此文章代码和逻辑,以及相关配置或原理。
发布并运行
如需要自己动手实践,可在文章底部提供的下载链接并点击下载本示例代码,这个项目的完整代码。它是在Servlet 3.0的容器(Tomcat7/8,本文章使用 Tomcat7)上构建和部署运行的。
提供用户名和密码(admin/123456)并点击提交,就会看到管理页面。如下图中所示 -
点击注销,将会自动跳转到登录页。如下图中所示 -
点击浏览器后退按钮,将会留在登录屏幕。如下所示 -
而已。下一篇文章将学习如何显示基于已登录用户的角色,使用Spring Security 标签显示 JSP/视图等等。
下载源代码