25.01.15 SpringSecurity 授权
//准备工作 在登录通过username查询用户时,把用户对应的角色即角色对应的菜单查出,
//根据用户的角色role rid来查询对应的菜单
public interface AdminMenuDao extends BaseMapper<AdminMenu> {
@Select("SELECT m.* FROM admin_menu m ,rel_role_menu rel WHERE m.mid = rel.mid AND rel.rid = #{id}")
List<AdminMenu> selectListByRid(Long id);
}
@Service("adminMenuService")
public class AdminMenuServiceImpl extends ServiceImpl<AdminMenuDao, AdminMenu> implements AdminMenuService {
@Resource
AdminMenuDao adminMenuDao;
@Override
public List<AdminMenu> listByRid(Long roleId) {
List<AdminMenu> allMenuList = adminMenuDao.selectListByRid(roleId);
List<AdminMenu> firstList = allMenuList.stream()
.filter(Objects::nonNull)
//过滤pid不是0的
.filter(AdminMenu::checkFirst)
.collect(Collectors.toList());
//筛选出子菜单
firstList.forEach(firstMenu ->{
List<AdminMenu> childList = allMenuList.stream()
.filter(Objects::nonNull)
//级联等比
.filter(menu -> firstMenu.getMid().equals(menu.getPid()))
.collect(Collectors.toList());
firstMenu.setChildList(childList);
});
return firstList;
}
}
//对上面lam的详细写法
List<AdminMenu> firstList = allMneus.stream()
.filter(Objects::nonNull)
.filter(new Predicate<AdminMenu>() {
@Override
public boolean test(AdminMenu adminMenu) {
return adminMenu.checkFirst();
}
}).collect(Collectors.toList());
firstList.forEach(firstMenu->{
List<AdminMenu> childList = allMneus.stream()
.filter(Objects::nonNull)
.filter(new Predicate<AdminMenu>() {
@Override
public boolean test(AdminMenu adminMenu) {
return adminMenu.getPid().equals(adminMenu.getMid());
}
}).collect(Collectors.toList());
firstMenu.setChildMenu(childList);
});
角色信息存入UserDetails
LoginUserDetails(用于拿到数据库信息的类)
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
//权限列表,暂时不考虑,所有的连接都没有权限
//从数据库,已经查询出 角色信息 和菜单信息 到adminUser
//角色授权,权限标识授权
//new 返回的 权限列表
List<GrantedAuthority> authorityList = new ArrayList<>();
//查询出 角色的信息
AdminRole adminRole = adminUser.getAdminRole();
if (adminRole != null){
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + adminRole.getCode());
authorityList.add(authority);
}
return authorityList;
}
角色授权
//配置类
http.authorizeRequests()
//地址/test1/f1只有角色super_admin可以访问,其他没有提到的地址,是没有设置权限的,只要认证成功,都可以访问
///test1/**
.antMatchers("/test1/f1").hasRole("super_admin")
.antMatchers("/test1/f2").hasRole("admin")
.antMatchers("/test1/f3","/test1/f4").hasAnyRole("super_admin","admin")
.antMatchers("/loginuser/**","/web/**").permitAll()
.anyRequest().authenticated();
角色继承
//配置类当中
@Bean
public RoleHierarchy roleHierarchy(){
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
//super_admin权限,大于 admin
hierarchy.setHierarchy("ROLE_super_admin > ROLE_admin");
return hierarchy;
}
权限标识授权
http.authorizeRequests()
//↑角色授权 ↓权限标识授权
.antMatchers("/test1/f5").hasAuthority("admin")
.antMatchers("/test1/f6").hasAuthority("test")
.antMatchers("/test1/f7").hasAnyAuthority("admin","test")
.antMatchers("/loginuser/**","/web/**").permitAll()
.anyRequest().authenticated();
自定义403
http.exceptionHandling().accessDeniedHandler((request,response,e)->createJSON(response,"无权限"));
//报错时显示
注解
开启注解权限的使用
修改 SecurityConfig类
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
@Secured
角色继承失效了
//角色继承失效了
@Secured({"ROLE_super_admin"})
@GetMapping("/f1")
public R f1(){
return R.ok("f1方法,只有super_admin可以访问");
}
@Secured("ROLE_admin")
@GetMapping("/f2")
public R f2(){
return R.ok("f2方法,只有admin可以访问");
}
//多个参数时要加{}
@Secured({"ROLE_super_admin","ROLE_admin"})
@GetMapping("/f3")
public R f3(){
return R.ok("f3方法,只有admin,super_admin可以访问");
}
@PreAuthorize
方法执行之前,生效的权限
不符合要求不会进入到方法中
控制当前的请求,能不能进入到方法里
//PreAuthorize角色继承生效了
@PreAuthorize("hasRole('ROLE_super_admin')")
@GetMapping("/f1")
public R f1(){
return R.ok("f1方法,只有super_admin可以访问");
}
@PreAuthorize("hasRole('ROLE_admin')")
@GetMapping("/f2")
public R f2(){
return R.ok("f2方法,只有admin可以访问");
}
@PreAuthorize("hasAnyRole('ROLE_super_admin','ROLE_admin')")
@GetMapping("/f3")
public R f3(){
return R.ok("f3方法,只有admin,super_admin可以访问");
}
@PreAuthorize("hasAuthority('admin')")
@GetMapping("/f5")
public R f5(){
return R.ok("f5方法,只有admin标识可以访问");
}
@PreAuthorize("hasAuthority('test')")
@GetMapping("/f6")
public R f6(){
return R.ok("f6方法,只有test标识可以访问");
}
@PreAuthorize("hasAnyAuthority('admin','test')")
@GetMapping("/f7")
public R f7(){
return R.ok("f7方法,只有admin,test标识可以访问");
}
@PostAuthorize
方法执行之后,返回之前生效
这个请求,可以进入到方法内部,不论是否拦截,都会执行方法
使用方式,和@PreAuthorize一样,只是生效的时机不一样
@PreFilter
对参数 进行过滤,参数类型必须是集合
//不是拦截是否允许访问,是过滤参数
@PreFilter("filterObject.roleId > 1 ")
@GetMapping("/f9")
public R f9(@RequestBody List<AdminUser> list){
return R.ok(list);
}
@PostFilter
对返回结果进行过滤,返回值必须是集合(不能有包装)
@Resource
AdminUserService adminUserService;
@PostFilter("filterObject.roleId > 1")
@GetMapping("/f10")
public List<AdminUser> f10(){
List<AdminUser> list = adminUserService.list();
return list;
}
//UserDetails的实现类的这个方法,可以用来存放权限
public Collection<? extends GrantedAuthority> getAuthorities(){}
自定义权限认证方法1通过官方api,获取权限列表,判断是否存在
@Component
public class JavasmExpressAuthorize {
public boolean f1(String code){
//code 用户的权限标识,如何判断 用户是否拥有这个权限标识
//获取当前登录的用户信息
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal!=null){
LoginUserDetails loginUserDetails = (LoginUserDetails) principal;
//获取 权限列表
Collection<? extends GrantedAuthority> authorities =
loginUserDetails.getAuthorities();
//判断 里面 是否包含字符串 code
return authorities.stream().anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(code));
}
return false;
}
}
//@bean对象.方法名,传入参数,
//如果返回true,允许访问当前方法
//如果返回false,不允许访问,没有权限
@PreAuthorize("@javasmExpressAuthorize.f1('admin')")
@GetMapping("/f11")
public R f11(){
System.out.println("=======================================f111");
return R.ok("f11111");
}
2,不使用官方的权限列表,自己去做判断,是否可以访问
@Component
public class JavasmPreAuthorize {
public boolean check(String code) {
//获取登录用户信息
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal != null) {
LoginUserDetails userDetails = (LoginUserDetails) principal;
//用户自己的 用户信息
AdminUser adminUser = userDetails.getAdminUser();
//获取权限列表
List<AdminAuthority> authorityList = adminUser.getAuthorityList();
//把 权限列表中,所有的code 都集合到一起
if (authorityList != null && authorityList.size() > 0){
//List<code>
List<String> codeList = authorityList.stream().map(AdminAuthority::getCode).collect(Collectors.toList());
//是否包含字符串
return codeList.contains(code);
}
}
return false;
}
}
@PreAuthorize("@javasmPreAuthorize.check('admin')")
@GetMapping("/f12")
public R f12(){
System.out.println("=======================================f12222");
return R.ok("f12222");
}
3.根据菜单,认证授权
@PreAuthorize("@javasmMenuAuthorize.check('/room/info')")
@GetMapping("/f13")
public R f13(){
return R.ok("f13");
}
@Component
public class JavasmMenuAuthorize {
public boolean check(String url){
//获取 用户信息
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal != null){
LoginUserDetails loginUserDetails = (LoginUserDetails) principal;
return loginUserDetails.checkMenu(url);
}
return false;
}
}
public boolean checkMenu(String url) {
if (adminUser!=null){
//获取 菜单信息
AdminRole adminRole = adminUser.getAdminRole();
if (adminRole != null){
//菜单列表,但是 菜单列表 是父子关系,现在需要把childList 也拿出来
List<AdminMenu> menuList = adminRole.getMenuList();
//menuList→stream→获取childList的流→url流
Stream<String> childMenuUrlList = menuList.stream()
//获取该用户的子菜单数据
.map(AdminMenu::getChildList)
//将上面获取到的自菜单列表转换成一个一个的流,在合并为一个单一的流
.flatMap(Collection::stream)
//获取菜单URL
.map(AdminMenu::getUrl);
//一级菜单url
Stream<String> firstMenuUrlList = menuList.stream().map(AdminMenu::getUrl);
//两个流合并到一起,重新组装
List<String> urlList = Stream.concat(childMenuUrlList, firstMenuUrlList)
.collect(Collectors.toList());
return urlList.contains(url);
}
}
return false;
}
//flastMap的完整写法
.flatMap(new Function<List<AdminMenu>, Stream<AdminMenu>>() {
@Override
public Stream<AdminMenu> apply(List<AdminMenu> adminMenus) {
return adminMenus.stream();
}
})
原文地址:https://blog.csdn.net/2401_87910368/article/details/145168482
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!