认证用户 [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" )