0%

认证用户

认证用户

[TOC]

  如果我们使用如下的最简单的配置,那么就能无偿地得到一个登陆页面:

1
2
3
4
5
package spitter.config;
......
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{}

  实际上,在重写configure(HttpSecurity)之前,我们都能使用一个简单却功能完备的登录页。但是,一旦重写了configure(HttpSecurity)方法,就是失去了这个简单的登录界面。不过,这个功能要找回也容易。我们只需要在configure(HttpSecurity)方法中,调用formLogin(),如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.formLogin()
.and()
.authorizeRequests()
.antMatchers("/spitter/me").hasRole("SPITTER")
.antMatchers(HttpMethod.POST,"/spittles").hasRole("SPITTER")
.anyRequest().permitAll()
.and()
.requiresChannel()
.antMatchers("/spitter/form").requiresSecure();
}

  如果我们访问应用的“/login”链接或者导航到需要认证的页面,那么将会在浏览器中展现登录界面。这个界面在审美上没什么令人兴奋的,但是它却能实现所需的功能。

添加自定义的登录页

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spitter</title>
<link rel="stylesheet"
type="text/css"
th:href="@{/resources/style.css}"></link>
</head>
<body onload='document.f.username.focus();'>
<div id="header" th:include="page :: header"></div>
<div id="content">

<a th:href="@{/spitter/register}">Register</a>


<form name='f' th:action='@{/login}' method='POST'>
<table>
<tr><td>User:</td><td>
<input type='text' name='username' value='' /></td></tr>
<tr><td>Password:</td>
<td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'>
<input id="remember_me" name="remember-me" type="checkbox"/>
<label for="remember_me" class="inline">Remember me</label></td></tr>
<tr><td colspan='2'>
<input name="submit" type="submit" value="Login"/></td></tr>
</table>
</form>
</div>
<div id="footer" th:include="page :: copy"></div>
</body>
</html>

启用HTTP Basic认证

  如果要启用HTTP Basic认证的话,只需要在configure()方法所传入的HttpSecurity对象上调用httpBasic()即可。另外,还可以通过调用realmName()方法指定域。如下是在Spring Security中启用HTTP Basic认证的典型配置:

1
2
3
4
5
6
7
8
9
10
11
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.formLogin()
.loginPage("/login")
.and()
.httpBasic()
.realmName("Spittr")
.and()
...
}1234567891011

在httpBasic()方法中,并没有太多的可配置项,甚至不需要什么额外配置。HTTP Basic认证要么开启,要么关闭。

启用Remember-me功能

  站在用户的角度来讲,如果应用程序不用每次都提示他们登录是更好的。这就是为什么许多站点提供了Remember-me功能。你只要登录过一次,应用就会记住你。
  Spring Security使得为应用添加Remember-me功能变得非常容易。只需要在configure()方法所传入的HttpSecurity对象上调用rememberMe()即可。

1
2
3
4
5
6
7
8
9
10
11
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.formLogin()
.loginPage("/login")
.and()
.rememberMe()
.tokenValiditySeconds(2419200)
.key("spittrKey")
...
}1234567891011

  默认情况下,这个功能是通过在Cookie中存储一个token完成的,这个token最多两周内有效。但是,在这里,我们指定这个token最多四周内有效(2,419,200秒)。存储在cookie中的token包含用户名、密码、过期时间和一个私匙——在写入cookie前都进行了MD5哈希。默认情况下,私匙的名为SpringSecured,但是这里我们将其设置为spitterKey,使他专门用于Spittr应用。
  既然Remember-me功能已经启用,我们需要有一种方式来让用户表明他们希望应用程序记住他们。为了实现这一点,登录请求必须包含一个名为remember-me的参数。在登录表单中,增加一个简单复选框就可以完成这件事:

1
2
<input id="remember-me" name="remember-me" type="checkbox"/>
<lable for="remember-me" class="inline">Remember me</label>12

退出

  其实,按照我们的配置,退出功能已经可以使用了,不需要再做其他的配置了。我们需要的只是一个使用该功能的链接。
  退出功能是通过Servlet容器的Filter实现的(默认情况下),这个Filter会拦截针对“/logout”的请求。在新版本的SpringSecurity中,出于安全的考虑(防止CSRF攻击),已经修改了LogoutFilter,使得Get方式的“/logout”请求不可用。必须以POST方式发起对该链接的请求才能生效。因此,为应用添加退出功能只需要添加如下表单即可(如下以Thymeleaf代码片段的形式进行了展现):

1
2
3
<form th:action="@{/logout}" method="POST">
<button type="submit">退出登录</button>
</form>

   提交这个表单,会发起对“/logout”的请求,这个请求会被Spring Security的LogoutFilter所处理。用户会退出应用,所有的Remember-me token都会被清楚掉。在退出完成后,用户浏览器将会重定向到“/login?logout”,从而允许用户进行再次登录。如果希望被重定向到其他的页面,如应用的首页,那么可以在configure()中进行配置:

1
2
3
4
5
6
7
8
9
10
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.formLogin()
.loginPage("/login")
.and()
.logout()
.logoutSuccessUrl("/")
...
}

除了logoutSuccessUrl()方法之外,你可能还希望重写默认的LogoutFilter拦截路径。我们可以通过调用logoutUrl()方法实现这一功能:

1
2
3
.logout()
.logoutSuccessUrl("/")
.logoutUrl("/signout")