基础环境搭建
创建springboot项目,写好几个测试的前端页面,以及Controller的实现,整体框架如下:
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<title>Title</title>
</head>
<body>
<div>首页</div>
<!--这个请求发送到后端,然后跳转到登陆页,如果用户没有登陆则显示 登陆 -->
<div sec:authorize="!authenticated"><a th:href="@{/toLogin}">登陆</a></div>
<!--得到用户名-->
用户名:<div sec:authentication="name"> </div>
<!--只显示角色对应有权限的组件-->
<div sec:authorize="hasRole('vip1')">
<a th:href="@{level1/1}">1-1</a>
<a th:href="@{level1/2}">1-2</a>
<a th:href="@{level1/3}">1-3</a>
</div>
<div sec:authorize="hasRole('vip2')">
<a th:href="@{level2/1}">2-1</a>
<a th:href="@{level2/2}">2-2</a>
<a th:href="@{level2/3}">2-3</a>
</div>
<div sec:authorize="hasRole('vip3')">
<a th:href="@{level3/1}">3-1</a>
<a th:href="@{level3/2}">3-2</a>
<a th:href="@{level3/3}">3-3</a>
</div>
<!--这个请求由security默认配置的/logout处理,只有用户登录了才显示 注销 -->
<div sec:authorize="authenticated"><a th:href="@{/logout}"> 注销</a></div>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--action的参数必须与后端loginProcessingUrl相同,因为这里请求的是security配置好的默认处理方法,
而不是我们自己写的Controller,所以对请求url,参数名等有严格要求,如需自定义需在后端进行同步配置。-->
<form th:action="@{/toLogin}" method="post">
<input type="text" value="用户名" name="username"/>
<input type="text" value="密码" name="password">
<input type="submit" value="登陆">
</form>
</body>
</html>
导入依赖的包(注意:spring-boot-starter-parent这个依赖版本需要在2.0.9以下,高版本有些功能无法使用)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
搭建好基本的项目之后可以运行访问所有的页面,然后使用aop的思想来实现权限,认证等。
创建UserService
创建一个业务类继承UserDetailService类,重写loadUserByName(String userName)方法
当然根据实际还要创建Dao等从数据库获得用户信息,我这里没有创建,而是伪造了一条数据.
注意:密码必须是要加密的,否则无法使用,如果数据库中存储的是加密数据可以取出来直接用,否则要进行加密。
public class UserService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
return new User("123",new BCryptPasswordEncoder().encode("123"), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_vip1"));
}
}
配置security类
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
/*配置权限,对应角色只能访问对应路径下的页面,角色名称是自定义的,用户只要根据自己的角色来跟
这里的角色对比即可等到用户具有哪些权限*/
http.authorizeRequests()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
/*
如果没有权限则跳到登陆页,没有写loginPage则跳到security定义好的登陆页。
loginProcessingUrl的参数必须与前端登录表单的action的参数一致,
另外前端表单的用户名和密码的name需为username和password,因为这个请求spring写好的请求,
参数不一致则会请求错误,当然后端也可以使用.userNameParameter("name")的方式配置参数名称.
*/
http.formLogin().loginPage("/toLogin").loginProcessingUrl("/toLogin");
//作用是关闭csrf攻击,否则无法实现自动注销
http.csrf().disable();
//注销成功则返回登陆页面
http.logout().logoutSuccessUrl("/toLogin"); //springboot2.1.0以下才有用
//记住我,前端选择框的名字设为rememberMe
//http.rememberMe().rememberMeParameter("rememberMe");
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/*绑定用户的信息,从而判断用户的权限
这里会自动调用重写的loadUserByName(String userName)方法来获得用户的信息
加密方式要与重写方法中返回值的密码加密方式一致。
*/
auth.userDetailsService(new UserService()).passwordEncoder(new BCryptPasswordEncoder());
}
}
运行结果
此时尝试输入地址访问页面也会跳到登陆界面
点击登录
点击对应组件就可以跳到对应的页面了,点击注销之后必须重新登陆才能访问。