记住我

现在的情况,我们只要登录之后,关闭浏览器,再登录,就会让我们重新登录,但是很多网站的情况,就是有一个记住密码的功能,这个该如何实现呢?很简单

1、开启记住我功能

1
2
3
4
5
6
//定制请求的授权规则
@Override
protected void configure(HttpSecurity http) throws Exception {
//开启记住我功能
http.rememberMe().rememberMeParameter("remember");
}

2、我们再次启动项目测试一下,发现登录页多了一个记住我功能,我们登录之后关闭 浏览器,然后重新打开浏览器访问,发现用户依旧存在!

思考:如何实现的呢?其实非常简单

我们可以查看浏览器的cookie

3、我们点击注销的时候,可以发现,spring security 帮我们自动删除了这个 cookie

4、结论:登录成功后,将cookie发送给浏览器保存,以后登录带上这个cookie,只要通过检查就可以免登录了。如果点击注销,则会删除这个cookie

定制登录页

现在这个登录页面都是spring security 默认的,怎么样可以使用我们自己写的Login界面呢?

1、在刚才的登录页配置后面指定 loginpage

1
2
3
4
5
6
// 开启自动配置的登录功能
// /login?error 重定向到这里表示登录失败
http.formLogin().loginPage("/tologin") //配置自己的登入页面
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login"); // 登陆表单提交请求

2、然后前端也需要指向我们自己定义的 login请求

1
2
3
4
<div class="btn-group btn-group-lg" >
<!--如果未登录-->
<button type="button" class="btn btn-default"><a th:href="@{/tologin}">登入</a></button>
</div>

3、我们登录,需要将这些信息发送到哪里,我们也需要配置,login.html配置提交请求及方式,方式必须为post:

loginPage()源码中的注释上有写明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<form th:action="@{/login}" method="post">
<div class="form-group has-feedback">
<input type="text" class="form-control" placeholder="Email" name="username">
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input type="password" class="form-control" placeholder="Password" name="password">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-8">
<div class="checkbox icheck">
<label>
<input type="checkbox" name="remember"> Remember Me
</label>
</div>
</div>
<!-- /.col -->
<div class="col-xs-4">
<button type="submit" class="btn btn-primary btn-block btn-flat">Sign In</button>
</div>
<!-- /.col -->
</div>
</form>

4、这个请求提交上来,我们还需要验证处理,怎么做呢?我们可以查看formLogin()方法的源码!我们配置接收登录的用户名和密码的参数!

1
2
3
4
5
6
// 开启自动配置的登录功能
// /login?error 重定向到这里表示登录失败
http.formLogin().loginPage("/tologin") //配置自己的登入页面
.usernameParameter("username") //接收前端参数username
.passwordParameter("password") //接收前端参数password
.loginProcessingUrl("/login"); // 登陆表单提交请求

5、在登录页增加记住我的多选框

1
2
3
4
5
6
7
<div class="col-xs-8">
<div class="checkbox icheck">
<label>
<input type="checkbox" name="remember"> Remember Me
</label>
</div>
</div>

6、后端验证处理!

1
2
//定制记住我的参数!
http.rememberMe().rememberMeParameter("remember");

7、测试,OK

完整配置代码

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package cn.panyucable.springboot.sercurity.config;

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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
* @version v1.0.0
* @ClassName: SecurityConfig
* @Description: TODO
* @Author: LYW
* @Date: 2020-04-20 11:44
*/

@Configuration
@EnableWebSecurity //开启WebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

// 定制请求的授权规则
@Override
protected void configure(HttpSecurity http) throws Exception {


http.authorizeRequests().antMatchers("/").permitAll() //首页所有人可以访问
.antMatchers("/level1/**").hasRole("vip1") //功能页只有对应的权限可以访问
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");

// 开启自动配置的登录功能
// /login?error 重定向到这里表示登录失败
http.formLogin().loginPage("/tologin") //配置自己的登入页面
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login"); // 登陆表单提交请求

//开启自动配置的注销的功能
// 默认为/logout 注销请求
http.logout().deleteCookies("remove").invalidateHttpSession(true).logoutSuccessUrl("/");

http.csrf().disable(); //关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求

//开启记住我功能
http.rememberMe().rememberMeParameter("remember");

}




//定义认证规则
//在内存中定义,也可以在jdbc中去拿,或者在xml中定义
//Spring security 5.0中新增了多种加密方式,也改变了密码的格式。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

//要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
//spring security 官方推荐的是使用bcrypt加密方式。
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("root").password(new BCryptPasswordEncoder().encode("root"))
.roles("vip1","vip2","vip3")
.and()
.withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip3");
}
}