我们使用这个springSecurity安全框架,作用是认证,授权,将用户的权限和对应的资源进行绑定,默认的是在内存中保存的,实际开发中,是需要根据项目业务的需求对某些方法进行重写,使数据库中权限对应的资源进行绑定,就是查看当前登录的用户所扮演的角色,该角色有哪些权限
授权
1内存交互资源绑定
这是框架默认的绑定方式,根据业务需求可以重写某些方法,连接数据库,进行交互进行资源绑定
inMemoryAuthentication
1创建一个SpringBoot项目
2配置类MySecurityConfig
package com.aaa.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {//加密@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();//新建密码加密器}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//内存交互auth.inMemoryAuthentication().withUser("zhangsan").password(passwordEncoder().encode("123456")).roles("admin").authorities("user:query", "user:delete", "user:update", "user:insert")//手动设置的用户权限绑定资源,有4个权限.and().withUser("lisi").password(passwordEncoder().encode("123456")).roles("test").authorities("user:query", "user:export")//有两个权限;}@Overrideprotected void configure(HttpSecurity http) throws Exception {//登录前http.formLogin().loginPage("/login.html").loginProcessingUrl("/mylogin").successForwardUrl("/success").failureUrl("/fail.html") // 直接指向一个HTML页面.permitAll();//登录后http.exceptionHandling().accessDeniedPage("/403.html");//禁止2跨域伪造请求的验证http.csrf().disable();http.authorizeRequests().anyRequest().authenticated();}
}
3添加注解
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启安全框架注解
4在controller层加注解
在对应的方法上加注解
@PreAuthorize(value="hasAnyAuthority('user:query')")
package com.aaa.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyUserController {@GetMapping("query")@PreAuthorize(value="hasAnyAuthority('user:query')")public String query(){System.out.println("访问查询资源");return "查询资源";}@GetMapping("delete")@PreAuthorize(value = "hasAuthority('user:delete')")public String delete(){System.out.println("访问删除资源");return "删除资源";}@GetMapping("update")@PreAuthorize(value = "hasAuthority('user:update')")public String update(){System.out.println("访问修改资源");return "修改资源";}@GetMapping("insert")@PreAuthorize(value = "hasAuthority('user:insert')")public String insert(){System.out.println("访问添加资源");return "添加资源";}@GetMapping("export")@PreAuthorize(value = "hasAuthority('user:export')")public String export(){System.out.println("访问导出资源");return "导出资源";}
}
2与数据库交互进行权限的资源绑定
1添加依赖
<!--添加依赖--><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><version>2.6.13</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.26</version></dependency>
2写属性文件
加载资源文件
3创建dao层和entity(实体类)
举一个接口和一个实体类例子
user-role-permission,
从用户表到角色表,再到权限表
sys_user--->sys_user_role--->sys_role_permission--->sys_permission
mybatis-plus先根据条件(用户的名)从用户表sys_user筛选,获取用户id,
然后拿着用户的id从用户角色表sys_user_role获取到用户所对应的roleid,
接着拿着roleid从角色权限表sys_role_permission获取permissionid,
再拿着权限id,(permissionid)到权限表sys_permission里获取所有全部权限信息,
最后绑定到用户上
sql语句
select DISTINCT sys_permission.* from sys_permission
join sys_role_permission
on sys_permission.perid=sys_role_permission.perid
join sys_user_role
on sys_role_permission.roleid=sys_user_role.roleid
where sys_user_role.userid=#{userid}
4 写自己的业务层
根据业务需求,重写框架的某些默认方法,进行权限绑定
package com.aaa.service;import com.aaa.dao.PermissionDao;
import com.aaa.dao.UserDao;
import com.aaa.entity.Permission;
import com.aaa.entity.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;@Service
public class MyUserDetailService implements UserDetailsService {@Autowiredprivate UserDao userDao;@Autowiredprivate PermissionDao permissionDao;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//完成根据账户查询数据库即可QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username",username);User user = userDao.selectOne(queryWrapper);if(user!=null){//permissions集合,源类型的集合,源集合--->目标类型的集合转换List<Permission> permissions = permissionDao.selectByUserId(user.getUserid());//空的SimpleGrantedAuthority类型的数组,目标类型的集合Collection<SimpleGrantedAuthority> authorities= new ArrayList<>();for (Permission per:permissions) {//把permissions集合里的东西拿出来,放到空集合里SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(per.getPercode());authorities.add(simpleGrantedAuthority);}org.springframework.security.core.userdetails.User userDetail =new org.springframework.security.core.userdetails.User(user.getUsername(),user.getUserpwd(),authorities);return userDetail;}return null;}}
5再配置类MySecurityConfig
用自己写的业务替换掉框架给的
package com.aaa.config;
import com.aaa.service.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailService myUserDetailService;@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//数据库交互auth.userDetailsService(myUserDetailService);//内存交互
// auth.inMemoryAuthentication()
// .withUser("zhangsan")
// .password(passwordEncoder().encode("123456"))
// .roles("admin")
// .authorities("user:query","user:delete","user:update","user:insert")
// .and()
// .withUser("lisi")
// .password(passwordEncoder().encode("123456"))
// .roles("test")
// .authorities("user:query","user:export")//;}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin().loginPage("/login.html").loginProcessingUrl("/mylogin").successForwardUrl("/success").failureUrl("/fail.html") // 直接指向一个HTML页面.permitAll();
// http.authorizeRequests()
// .antMatchers("/query").hasAnyAuthority("user:query")
// .antMatchers("/delete").hasAnyAuthority("user:delete")
// .antMatchers("/update").hasAnyAuthority("user:update")
// .antMatchers("/insert").hasAnyAuthority("user:insert")
// .antMatchers("/export").hasAnyAuthority("user:export");http.exceptionHandling().accessDeniedPage("/403.html");//禁止2跨域伪造请求的验证http.csrf().disable();http.authorizeRequests().anyRequest().authenticated();}
}
总结
根据业务需求调用自己的业务层(自己写的),去代替框架的部门业务实现需求