至少离不开五张表(最基本的)
1.概述用户表,
角色表,
权限表,
(角色表和权限表可能是多对多)角色和权限的中间表,
用户表和角色表的中间表,
SpringSecurity VS ShiroSpring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
认证和授权1、Spring Security 基于Spring 开发,项目若使用 Spring 作为基础,配合 Spring Security 做权限更加方便,而 Shiro 需要和 Spring 进行整合开发;
2、Spring Security 功能比 Shiro 更加丰富些,例如安全维护方面;
3、Spring Security 社区资源相对比 Shiro 更加丰富;
4、Shiro 的配置和使用比较简单,Spring Security 上手复杂些;
5、Shiro 依赖性低,不需要任何框架和容器,可以独立运行;Spring Security 依赖Spring容器;
2.SpringBoot整合SpringSecurity什么是认证?
认证 - 简单的来讲就是校验身份信息,确定用户身份是否有效(你是谁?)
例如使用传统的账号密码校验(类似于appId和密钥)和使用session和token校验等。
什么是授权?
授权简单的来讲就是校验权限,确定有效用户是否有权限访问资源(你能做什么?)
2.1 添加依赖
org.springframework.boot spring-boot-starter-security
2.2 配置核心适配器
import com.qf.authserver.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//禁用基本认证方式
.httpBasic().disable()
//禁用csrf防御
.csrf().disable()
//开启表单认证
.formLogin()
//配置访问登录页的url
.loginPage("/toLogin")
//配置进行登录发送的请求,Security会处理该url进行登录认证
.loginProcessingUrl("/goLogin")
//登录失败后触发的url
.failureForwardUrl("/toLogin?error=1")
//登录成功后触发的url
.successForwardUrl("/toIndex")
//表示前面的请求都放行
.permitAll()
.and()
.logout()
//配置注销的url
.logoutUrl("/logout")
//放行注销请求
.permitAll()
.and()
//任意请求都要通过授权访问
.authorizeRequests().anyRequest().permitAll();
}
}
注意:一但接入了SpringSecurity之后,登录认证的过程必须交给SpringSecurity来做,默认用户名user,密码会在控制台出现
2.3 自己写的login
Title
登录页
用户名或者密码错误
2.4 提供跳转到页面的Controller方法
@RequestMapping("/tologin")
public String toLogin(){
return "login";
}
2.5 自定义认证过程
思考:
1.如何让SpringSecurity使用我们自己的认证过程?(比如访问数据库)
2、如何让SpringSecurity知道我们自己创建的User对象(或其他对象)代表当前认证用户?
2.6 自定义认证业务实现指定接口
import org.springframework.security.core.userdetails.UserDetailsService;
public interface IUserService extends UserDetailsService {
}
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements IUserService {
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//访问数据库认证用户信息
return null;
}
}
2.7 自定义用户对象实现指定接口 (UserDetails)
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable, UserDetails {
private Integer id;
private String username;
private String password;
private String name;
@Override
public Collection extends GrantedAuthority> getAuthorities() {
//返回当前用户角色/权限信息
return null;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
2.8 配置自定义认证,在security核心适配器重写配置
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
}
从security4.0以后,密码必须配置加密方式,如果密码没有加密,就会报以上的错误
2.9 自定义鉴权过程
@Component
public class PerssionHandler {
private AntPathMatcher antPathMatcher = new AntPathMatcher();
public boolean hasPerssion(HttpServletRequest request, Authentication authentication){
//判断当前发送的请求的url
String requestURI = request.getRequestURI();
//判断是否通过了身份认证
Object principal = authentication.getPrincipal();//该方法可以获得通过了security身份认证的UserDetails对象
if(principal instanceof UserDetails){
//说明当前已经通过了身份认证
//进行权限的判定
UserDetails user = (UserDetails) principal;
//获得当前登录用户的所有权限
Collection extends GrantedAuthority> authorities = user.getAuthorities();
for (GrantedAuthority authority : authorities) {
System.out.println("请求的url:" + requestURI + " 拥有的url:" + authority.getAuthority());
if (antPathMatcher.match(requestURI, authority.getAuthority())){
System.out.println("拥有该权限!");
//拥有权限
return true;
}
}
System.out.println("权限不足!");
}
return false;
}
}
2.10 配置鉴权方法,核心适配器
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().loginPage("/tologin")
.loginProcessingUrl("/gologin")
.failureUrl("/tologin?error=1").permitAll()
.and()
.logout().permitAll()
.and()
.authorizeRequests()
//配置静态资源放行
.mvcMatchers("/static/**", "*.js", "*.css").permitAll()
//配置首页需要身份认证
.mvcMatchers("/").authenticated()
//配置其他所有请求需要通过自定义方法的鉴权
.anyRequest().access("@perssionHandler.hasPerssion(request, authentication)")
.and()
.csrf().disable()
//配置权限不足时抛出的url
.exceptionHandling().accessDeniedPage("/noperssion");
}



