版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangb_java/article/details/86490235
表单登录即在form表单中输入用户名/密码,提交登录,在spring security中默认配置了formLogin来实现表单登录。
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
控制层
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello world";
}
启动项目
请求http://localhost:8080/hello 系统判定你没有权限,会自动跳转到预置页面/login要求你先登录。
同时系统也给我们预置了一个用户,用户名是user,密码显示在启动控制台中。
登录成功,会自动跳回到最初访问的地址http://localhost:8080/hello
预置url和页面
之所以会有以上效果,是因为formLogin自动配置了一些url和页面:
- /login (get):登录页面,任意没有登录的请求都会跳转到这里,就是上面看到的那个页面。
- /login (post):登录接口,在登录页面点击登录,会请求这个接口。
- /login?error:用户名或密码错误,跳转到该页面。
- /:登录成功后,默认跳转的页面,/会重定向到index.html,这个页面要你自己实现。
- /logout:注销页面。
- /login?logout:注销成功跳转页面。
可以看出,默认配置将前后端整合在一起,而我们更希望是前后端分离,也不需要那些预置页面,此时就要自定义配置。
自定义前后端分离
注意看这段代码的缩进距离,http是根对象,其下有4个配置项:authorizeRequests、formLogin、logout、csrf,缩进距离是一样的。每个配置项使用and方法分隔连接,and前面是当前配置项的下级参数配置,缩进更多。
@SpringBootConfiguration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()//配置权限
.anyRequest().authenticated()//任意请求需要登录
.and()
.formLogin()//开启formLogin默认配置
.loginPage("/login/auth").permitAll()//请求时未登录跳转接口
.failureUrl("/login/fail")//用户密码错误跳转接口
.defaultSuccessUrl("/login/success",true)//登录成功跳转接口
.loginProcessingUrl("/login")//post登录接口,登录验证由系统实现
.usernameParameter("username") //要认证的用户参数名,默认username
.passwordParameter("password") //要认证的密码参数名,默认password
.and()
.logout()//配置注销
.logoutUrl("/logout")//注销接口
.logoutSuccessUrl("/login/logout").permitAll()//注销成功跳转接口
.deleteCookies("myCookie") //删除自定义的cookie
.and()
.csrf().disable(); //禁用csrf
}
- 未登录用户请求/hello会跳转到/login/auth接口,但这个接口本生也需要登录才能请求,所以其配置了permitAll允许任何人请求,包含未登录用户。/login/logout也是同理。其他接口没有配置permitAll,因为它们已经处于登录状态,或者会被特别处理,如登录接口只会被特定过滤器拦截处理,以后会讲。
- true:是指登录成功后,始终跳转到登录成功url。它默认为false,就像上面请求/hello时未登录,跳转到登录页面。而登录成功后又自动跳回到/hello,而不是跳转到登录url,这显然不符合前后端分离模式。
- 在登录时,如果手动创建了cookie,可以用deleteCookies方法删除。如果是系统自动创建的一些数据,在注销时系统会自动清理。如果还有cookie以外的自定义数据可在注销成功接口去清理。
- csrf().disable():csrf功能默认会开启,用于防止跨站伪造请求,以后会讲,现在先禁用,否则将无法登录。
自定义接口实现
为上面配置的url添加简单的rest实现,/login登录接口由系统实现,不用我们管。
@RestController
public class LoginController {
@GetMapping("/login/{status}")
public String login(@PathVariable String status) {
System.out.println(status);
if("auth".equals(status)){
return "没有登录";
}
if("fail".equals(status)){
return "登录失败";
}
if("success".equals(status)){
return "登录成功";
}
if("logout".equals(status)){
return "注销成功";
}
return "";
}
login.html
前后端分离只能用ajax请求,以jquery为例。/login就是上面loginProcessingUrl中配置,默认为post方法,username和password参数和上面配置的参数名对应。
<p>
<label>Username</label> <input id="username">
</p>
<p>
<label>Password</label> <input id="password">
</p>
<button onclick="login()">Sign in</button>
<script src="/jquery.min.js"></script>
<script>
function login(){
$.ajax({
url : "/login" ,
type : 'post',
data : {
username: $("#username").val(),
password: $("#password").val(),
},
success : function(data) {
alert(data);
}
});
}
</script>