通过狂神发布在B站的视频,了解到spring security(以下简称ss)在权限控制的强大好用,故学之。
一、详细例子
数据库
pom.xml
导入必要的包
<!-- security和thymeleaf的整合包-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<!-- security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
配置
- 创建SecurityConfig(继承 WebSecurityConfigurerAdapter )
- 授权configure(HttpSecurity http)
- 认证(configure(AuthenticationManagerBuilder auth)(连接数据库)
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启方法权限控制
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Bean
PasswordEncoder passwordEncoder(){
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人能访问,功能页只有对应权限的人才能看到
http.authorizeRequests()
.antMatchers("/","/login.html","/register.html").permitAll()
.antMatchers("/level1/**").hasAnyRole("USER","COMPANY")
.antMatchers("/level2/**").hasRole("COMPANY")
.antMatchers("/level3/**").hasRole("ADMIN");
}
//认证: 注入自定义userService
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(new MyPasswordEncoder());
}
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
sevice
- 认证——在sevice层的部分 (注入数据库操作)
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//从数据库获取该用户
User user = userDao.findByUsername(username);
//--------------认证账号
if (user == null){
throw new UsernameNotFoundException("用户不存在");
}
//----------开始授权
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
if (!StringUtils.isEmpty(user.getRoles())) {
String[] roles = user.getRoles().split(",");
for (String role : roles) {
if (!StringUtils.isEmpty(role)) {
authorities.add(new SimpleGrantedAuthority(role.trim()));
}
}
}
return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),authorities);
}
工具类
- 自定义验证密码类 密码比较器
public class MyPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return MD5Utils.encode((String) charSequence);
}
@Override
public boolean matches(CharSequence charSequence, String encodedPassword) {
//user Details Service验证
return encodedPassword.equals(MD5Utils.encode((String) charSequence));
}
}
public class SpringSecurityUtil {
public static Authentication getAuthentication(){
return SecurityContextHolder.getContext().getAuthentication();
}
public static Collection<? extends GrantedAuthority> getAllPermission(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
return authorities;
}
public static boolean hasPermission(String permission){
if(StringUtils.isEmpty(permission)){
return false;
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
boolean hasPermission = false;
for(GrantedAuthority grantedAuthority : authorities){
String authority = grantedAuthority.getAuthority();
if(authority.equals(permission)){
hasPermission = true;
}
}
return hasPermission;
}
public static User getUser(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return (User) authentication.getPrincipal();
}
public static void logout(){
SecurityContextHolder.clearContext();
}
}
UserController
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username,password);
//用spring Security拦截登录请求,进行认证和授权
Authentication authenticate = myAuthenticationManager.authenticate(usernamePasswordAuthenticationToken);
SecurityContextHolder.getContext().setAuthentication(authenticate);
HttpSession session = request.getSession();
//关系到验证后的登录
session.setAttribute("SPRING_SECURITY_CONTEXT",SecurityContextHolder.getContext());```
html
<div class="container">
<!-- 未登录-->
<div sec:authorize="!isAuthenticated()">
<a th:href="@{/user/toLogin}">登录</a>
</div>
<!--已登录-->
<div sec:authorize="isAuthenticated()">
用户名:<span sec:authentication="name"></span>
<a th:href="@{/user/toLogout}">退出登录</a>
</div>
<div>
<div class="content" sec:authorize="hasAnyRole('USER','COMPANY')">
<h5 class="content">普通用户</h5>
<hr>
<div><a th:href="@{/level1/updatePassword}">修改密码</a></div>
<div><a th:href="@{/level1/userRequirementList}">查看需求表,进行报名</a></div>
</div>
<div class="content" sec:authorize="hasRole('COMPANY')">
<h5 class="content">企业用户</h5>
<hr>
<div><a th:href="@{/level2/selectAllReq}">查找所有需求</a></div>
<div><a th:href="@{/level2/selectEnroll}">查看报名列表并审核</a></div>
</div>
<div class="content" sec:authorize="hasRole('ADMIN')">
<h5 class="content">管理员</h5>
<hr>
<div><a th:href="@{/level3/identityList}">审核用户认证</a></div>
<div><a th:href="@{/level3/requirementReadList}">需求审核列表</a></div>
</div>
</div>
</div>
二、原理
-
auth.userDetailsService
-
Authentication getAuthentication
-
boolean hasPermission
-
Collection<? extends GrantedAuthority> getAllPermission()
-
User getUser()
-
UsernamePasswordAuthenticationToken
择日详述