Spring 27 Spring Security – 用户登出、CSRF、用户信息

作者 柚爸

用户登出

用户登出的动作是实际上是清除Session中的用户数据,开发的方法如下:

  1. 配置文件中加上登出的功能和对应的路径
  2. 在JSP页面中添加一个登出按钮
  3. 在登录表单页面中加入登出的消息

先来修改配置文件:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().anyRequest().authenticated()
        .and()
        .formLogin().loginPage("/showMyLoginPage").loginProcessingUrl("/authenticateTheUser")
        .permitAll()
        .and().logout().permitAll();
}

这里加入了.and()用来开启另外一个配置,然后配置了.logout().permitAll(),这表示添加了默认的/logout路径用于登出。

和用于提交登录表单的地址一样,这个/logout路径也无需编写控制器。注意这个方法默认只接受POST请求,所以要用一个空表单发一个POST请求到这个地址。

当有POST请求发到这个地址的时候,Spring Security会让会话失效,然后重定向到登录页面,并且会加上一个参数?logout

因为加上了?logout参数,所以可以用JSTL在这里也做一个提示。

现在在登录后的页面上加入一个logout按钮,需要在一个表单里:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>Spring Security学习</title>
</head>
<body>
<p>欢迎登录</p>
<form:form method="post" action="${pageContext.request.contextPath}/logout">
    <button type="submit">Logout</button>
</form:form>

</body>
</html>

最后修改登录页面,如果有logout参数就显示一段信息:

<c:if test="${param.logout != null}">
    <p style="color: brown">You have logged out!</p>
</c:if>

然后启动项目来实验一下,成功了,这就是用户登录和登出的初步。

CSRF

CSRF已经很熟悉了,来看一下Spring里如何在表单中埋CSRF token。

Spring Security使用Synchronizer Token Pattern,每一个请求都包含一个session和cookie,其中有一个随机生成的token,Spring Security每次都会验证这个token是否有效,这一切都是自动进行的。

CSRF主要用于Web应用,如果做一个不使用浏览器的服务,则不一定要开启CSRF。

要使用CSRF,必须使用POST请求,<form:form>自动会生成CSRF token字段,在刚才我们的登录表单里,可以看到有一个隐藏的部分:

<input type="hidden" name="_csrf" value="8f2b80b2-5295-4559-8d7c-be16186a5908">

这个就是CSRF token。如果不使用表单标签,那么就需要手动来添加CSRF字段。将登录表单的<form:from>修改成不使用Spring MVC 表单标签的<form>,此时登录,即使输入正确的用户名和密码,也会被服务器报403响应。

这个时候就需要手工添加CSRF信息如下:

<form action="" method="post">
    <input type="hidden" name="${_csrf.parameterName}" value="${_crsf.token}">
</form>

虽然名字有点怪,但是这么写了以后,确实能够生成CSRF TOKEN,也就可以正常登录了。
在Spring Security中关闭CSRF的方法是配置方法中http.csrf().disable()

显示用户信息

在用户登录的功能里,常见的是显示用户的名称,很多网站在登录之后都会显示名称,其实后台就是如何从session中获取用户信息,这里需要学习一下。

我们想在登录后的页面里显示用户的姓名和角色等信息,Spring Security为JSP提供了特殊的标签库用于显示用户相关信息,这个标签叫做Spring Security JSP Tag Library。

我们需要在POM中添加这个依赖,然后就可以在JSP页面中使用这个标签库来显示用户信息了。

需要添加的依赖如下:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>${springsecurity.version}</version>
</dependency>

在JSP页面中导入这个标签库:

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

之后就可以使用标签了,这两个标签比较长:

<p>
    User: <security:authentication property="principal.username"/>
    <br><br>
    Roles: <security:authentication property="principal.authorities"/>
    <br><br>
</p>

注意,这里用户名是正确的,角色显示自动将我们设置的角色字符串加上了[ROLE_****]。注意ROLE还可以同时配置多个:

.withUser(users.username("jenny").password("test123").roles("ADMIN","MANAGER"))

这样配置的话,在页面里显示出来就是:

Roles: [ROLE_ADMIN, ROLE_MANAGER]

用户登录登出和展示用户名的内容基本上了解了,然后就是权限,也就是基于角色来控制可以访问哪些URL。