这里记录一下Spring Security对登录用户请求访问页面的一些基本的授权控制,页面已经准备好,前端使用Thymeleaf模板引擎
用户授权管理
自定义访问控制
在之前也提到,需要自定义访问请求的权限控制,则需要在配置类中添加相应的接口配置,即重写configue(HttpSecurity http)
/*开启安全管理配置*/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
/*自定义身份认证*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/*密码编译器*/
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
/*1.基于内存的身份认证*/
// auth.inMemoryAuthentication().passwordEncoder(encoder)
// .withUser("admin").password(encoder.encode("admin")).roles("admin")
// .and()
// .withUser("cai").password(encoder.encode("123457")).roles("common");
/*2.使用UserDetails进行身份认证*/
auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
}
/*自定义用户权限*/
@Override
protected void configure(HttpSecurity http) throws Exception {
/*自定义访问控制*/
http.authorizeRequests()
//表示放行“/”访问,可根据自己需要调整
.antMatchers("/").permitAll()
//根据用户拥有的不同权限配置访问权限
.antMatchers("/admin/**").hasAuthority("admin")
.antMatchers("/common/**").hasAuthority("common")
.and()
.formLogin();
}
}
自定义用户登录页面
在之前项目中的登录一直使用的是Spring Security自带的登录页面,如果需要使用自己的登录页面
登录页面login.html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1,shrink-to-fit=no">
<title>用户登录界面</title>
<link rel="stylesheet" th:href="@{/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/signin.css}">
</head>
<body>
<!--SpringSecurity:登录提交数据验证的请求路径必须和跳转到登录页的请求路径一致-->
<form class="form-signin" th:action="@{/toLoginPage}" method="post">
<img class="mb-4" width="72" height="72" th:src="@{/login/img/login.jpg}">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">请登录</h1>
<div style="color: red" th:text="${logintips}"></div>
<!-- *************** -->
<input type="text" class="form-control" required="" autofocus="" name="username" th:placeholder="#{login.username}">
<input type="password" class="form-control" required=""name="password" th:placeholder="#{login.password}">
<div class="checkbox mb-3">
<label><input type="checkbox" name="rememberme">[[#{login.rememberme}]]</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.button}">登录</button>
<!-- *************** -->
<p class="mt-5 mb-3 text-muted">© <span th:text="${currentYear}">2020</span>-<span th:text="${currentYear}+1">2019</span></p>
<a class="btn btn-sm" th:href="@{/toLoginPage(langurage='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/toLoginPage(langurage='en_US')}">English</a>
</form>
</body>
</html>
登录提交数据验证的请求路径必须和跳转到登录页的请求路径一致
跳转到登录页的Controller接口
/*访问登录页*/
@GetMapping("/toLoginPage")
public String toLogingPage(Model model)S
{
//设置当前年份
model.addAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR));
return "login";
}
路径一致
login.html登录页提交登录数据验证的路径
<form class="form-signin" th:action="@{/toLoginPage}" method="post">
- 访问登录页的请求路径
@GetMapping("/toLoginPage")
在SecurityConfig配置类内设置
SecurityConfig是之前就已经写好的Spring Security配置类,这里面需要加入几行代码,在重写的configure(HttpSecurity http)方法内部编写
- 允许登录页
login.html能够访问 - 自定义登录页控制(登录页对应的请求页、接受用户名和密码参数名、登陆成功跳转的路径、失败跳转的路径)
/*自定义用户权限*/
@Override
protected void configure(HttpSecurity http) throws Exception {
/*自定义登录页*/
http.formLogin()
//开放访问权限,所有请求均可访问
.loginPage("/toLoginPage").permitAll()
//对应页面表单的name属性
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/")
//失败路径
.failureUrl("/toLoginPage?error");
}
这样,就完成了自定义登录页面的需求
自定义用户退出
注销功能的实现比较简单,只需要简短的两行代码就能实现
首先提供一个注销的表单
<form th:action="@{/mylogout}" method="post">
<input th:type="submit" th:value="注销" />
</form>
配置securityConfig
同样是在configure(HttpSecurity http)方法内部编写
/*自定义用户退出*/
http.logout()
.logoutUrl("/mylogout") //注销对应的请求路径
.logoutSuccessUrl("/"); //注销后跳转的路径
前端页面控制
不同的用户有不同的角色,因此有时候在一个页面中,希望普通用户能看到公共的内容,而管理员用户能看到一些内部的链接内容,这里借助Thymeleaf简单实现以下这个需求
pom引入相关依赖
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
在需要进行控制的页面引入安全标签库
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
页面上使用安全标签
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<!--是否匿名访问(未登录)-->
<div sec:authorize="isAnonymous()">
<h2 align="center">游客你好,如果想进行操作<a th:href="@{/toLoginPage}">请登录</a> </h2>
</div>
<!--是否进行身份认证(已登录)-->
<div sec:authorize="isAuthenticated()">
<!--sec:authentication="name":登录用户的用户名-->
<h2 align="center">你好,<span sec:authentication="name"></span>,
你拥有的权限:
<!--sec:authentication="principal.authorities":登录用户的权限-->
<span sec:authentication="principal.authorities"></span>
,你可进行如下操作</h2>
<form th:action="@{/mylogout}" method="post">
<input th:type="submit" th:value="注销" />
</form>
</div>
<!--根据不同的用户权限划分可显示的区域-->
<!--用户拥有common权限才可展示-->
<div sec:authorize="hasAuthority('common')">
<p><a th:href="@{/common/ArticleList}">查看列表</a></p>
</div>
<!--用户拥有admin权限才可展示-->
<div sec:authorize="hasAuthority('admin')">
<p><a th:href="@{/admin/toUpload}">上传</a></p>
<p><a th:href="@{/admin/toDownload}">下载</a></p>
</div>
</body>
</html>
后端接口获取用户信息
同样,在后端也可以通过调用Security的接口,获取已登录的用户信息
/*获取用户信息*/
@RequestMapping("/getUserInfo")
@ResponseBody
public String getUserInfo()
{
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
/*获取安全环境上下文*/
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
/*获取封装了用户信息的userDetails对象*/
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
//获取用户名
String str="用户名:"+userDetails.getUsername();
str = str+";用户权限:(";
//遍历用户权限并拼接字符串
for(GrantedAuthority authority:userDetails.getAuthorities())
{
System.out.println(authority.toString());
str= str+ authority.toString()+",";
}
str=str+")";
return str;
}