如何基于SpringSecurity的@PreAuthorize实现自定义权限校验方法

下面是详细攻略。

1. SpringSecurity基本概念

SpringSecurity是基于Spring框架的安全认证和授权模块,可以为我们的应用提供强大的安全管理。在SpringSecurity中,每个用户都有一个唯一的用户名和一个密码,SpringSecurity会在用户登录时对这些信息进行校验,如果校验通过则允许用户进行下一步操作,否则拒绝用户进行任何的操作。在SpringSecurity中,要进行权限的校验,需要有一个认证和授权的机制,SpringSecurity会将其封装成一个安全上下文,使用该上下文实现用户身份认证和授权。

2. 自定义权限校验方法

在SpringSecurity中,@PreAuthorize注解是进行权限校验的主要方式之一,它可以用于Controller层的每个方法。@PreAuthorize是一种基于Expression的权限校验机制,可以借助Spring Security传递的SecurityContext进行权限校验。

下面是一些常用的Expression:

  • hasRole: 判断用户是否具有角色,比如ROLE_ADMIN
  • hasAuthority: 判断用户是否有权限,比如EDIT
  • hasIpAddress: 判断用户是否来自指定的IP地址
  • hasPermission: 判断用户是否有指定的权限

我们可以通过在Controller上加上@PreAuthorize注解,并在注解中指定Expression来实现权限校验。

下面是一个示例:

@RestController
@RequestMapping("/api/v1")
public class UserController {

    @GetMapping("/user/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<User> findById(@PathVariable Long id) {
        User user = userService.findById(id);
        return ResponseEntity.ok(user);
    }
}

在上面的示例中,@PreAuthorize注解中的Expression是"hasRole('ADMIN')",表示只有具有ADMIN角色的用户才能访问该接口。

但是,上述示例中的Expression是写死的,如果我们需要根据不同的业务需求来动态判断用户的访问权限,就需要自定义权限校验方法。下面是自定义权限校验方法的步骤:

  1. 创建一个自定义的PermissionEvaluator实现类,实现hasPermission()方法,并注入到Spring容器中。hasPermission()方法的第一个参数代表SecurityContext,第二个参数代表当前的Object对象,第三个参数代表权限字符串。
@Component
public class MyPermissionEvaluator implements PermissionEvaluator {

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        if (authentication == null || !permission.equals("edit")) {
            return false;
        }

        User user = (User) authentication.getPrincipal();
        Long userId = user.getId();

        if (targetDomainObject instanceof User) {
            return ((User) targetDomainObject).getId().equals(userId);
        } else if (targetDomainObject instanceof Comment) {
            Comment comment = (Comment) targetDomainObject;
            return comment.getUserId().equals(userId);
        } else {
            return false;
        }
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        throw new UnsupportedOperationException();
    }
}
  1. 在Controller上使用@PreAuthorize注解,指定自定义的权限校验方法,使用"#target"代表需要校验的对象。
@RestController
@RequestMapping("/api/v1")
public class UserController {

    @GetMapping("/user/{id}")
    @PreAuthorize("@myPermissionEvaluator.hasPermission(authentication, #user, 'edit')")
    public ResponseEntity<User> findById(@PathVariable("id") User user) {
        return ResponseEntity.ok(user);
    }
}

在上面的示例中,@PreAuthorize注解中使用自定义的权限校验方法"myPermissionEvaluator.hasPermission()",指定了需要校验的对象为"#user",权限字符串为"edit"。

3. 自定义权限校验方法示例

下面是两个自定义权限校验方法的示例:

示例一:根据当前用户的角色动态校验权限

@Component
public class MyPermissionEvaluator implements PermissionEvaluator {

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        if (authentication == null || !(targetDomainObject instanceof User)) {
            return false;
        }

        User user = (User) authentication.getPrincipal();
        List<String> roles = user.getRoles();

        if ("edit".equals(permission)) {
            if (roles.contains("ROLE_ADMIN")) {
                return true;
            } else if (roles.contains("ROLE_EDITOR")) {
                return ((User) targetDomainObject).getEditorId() == user.getId();
            }
        } else if ("view".equals(permission)) {
            return true;
        }
        return false;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        throw new UnsupportedOperationException();
    }
}

在上述示例中,我们根据当前用户的角色动态判断用户的访问权限,如果用户具有ROLE_ADMIN角色,则允许访问;如果用户具有ROLE_EDITOR角色,则只能访问自己的文章。

示例二:根据权限字符串判断用户是否有权限访问资源

@Component
public class MyPermissionEvaluator implements PermissionEvaluator {

    @Autowired
    private ResourceDao resourceDao;

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        if (authentication == null || !(targetDomainObject instanceof String)) {
            return false;
        }

        String url = (String) targetDomainObject;
        Resource resource = resourceDao.findByUrl(url);
        if (resource == null) {
            return false;
        }

        List<Role> roles = resource.getRoles();
        List<String> roleNames = roles.stream().map(Role::getName).collect(Collectors.toList());

        return authentication.getAuthorities().stream().anyMatch(authority -> roleNames.contains(authority.getAuthority()));
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        throw new UnsupportedOperationException();
    }
}

在上述示例中,我们根据权限字符串判断用户是否有权限访问资源,如果url可以匹配到Resource,则从中获取角色列表,再与当前用户的角色进行比较,如果有相同的角色,则允许用户访问。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:如何基于SpringSecurity的@PreAuthorize实现自定义权限校验方法 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • java实现多线程文件的断点续传

    针对“java实现多线程文件的断点续传”的完整攻略,我会从以下几个方面进行详细讲解: 文件断点续传的原理介绍 Java多线程实现文件断点续传的步骤 代码实现示例 常见问题及解决方案 接下来,我会一一解释。 1. 文件断点续传的原理介绍 在进行文件断点续传之前,我们需要了解一下文件的上传、下载原理,具体过程如下:1. 通过输入或选择框选择要上传/下载的文件2.…

    Java 2023年5月19日
    00
  • SpringBoot整合Spring Security的详细教程

    SpringBoot整合SpringSecurity的详细教程 Spring Security是Spring框架家族中的一员,是基于Spring的实现了安全控制的框架。 SpringBoot是一个快速开发的框架,整合SpringSecurity可以让开发者快速实现安全控制功能。 下面我们一步步的来学习如何在SpringBoot中整合SpringSecurit…

    Java 2023年5月15日
    00
  • java数据库唯一id生成工具类

    Java数据库唯一ID生成工具类是用于在关系型数据库中生成唯一ID的工具类。在开发中,经常需要使用唯一ID作为数据库表的主键,而使用数据库自增长的整数或GUID字符串作为主键,会存在一些问题,如分布式环境下高并发的ID生成、算法不唯一等问题。因此,使用Java数据库唯一ID生成工具类,可以解决这些问题。 下面给出一个完整的攻略,介绍如何使用Java数据库唯一…

    Java 2023年5月20日
    00
  • Java Spring MVC获取请求数据详解操作

    在Java Spring MVC中,获取请求数据是Web开发中的常见需求。本文将详细讲解如何获取请求数据,并提供两个示例说明。 获取请求参数 在Spring MVC中,我们可以使用@RequestParam注解来获取请求参数。下面是一个示例: @PostMapping("/login") public String doLogin(@Re…

    Java 2023年5月18日
    00
  • Spring Boot 项目代码混淆,实战来了,再也不用担心代码泄露了!

    编译 简单就是把代码跑一哈,然后我们的代码 .java文件 就被编译成了 .class 文件 反编译 就是针对编译生成的 jar/war 包 里面的 .class 文件 逆向还原回来,可以看到你的代码写的啥。 比较常用的反编译工具 JD-GUI ,直接把编译好的jar丢进去,大部分都能反编译看到源码: 那如果不想给别人反编译看自己写的代码呢? 怎么做? 混淆…

    Java 2023年4月27日
    00
  • Spring Boot实战之静态资源处理

    让我来分步骤地讲解一下“Spring Boot实战之静态资源处理”的完整攻略。 1. 确认静态资源目录 首先要确认静态资源目录的配置是否正确。Spring Boot默认会将位于src/main/resources/static、src/main/resources/public、src/main/resources/resources、src/main/re…

    Java 2023年5月19日
    00
  • JavaWeb实现学生信息管理系统(2)

    “JavaWeb实现学生信息管理系统(2)”是一篇教程文章,旨在介绍如何使用JavaWeb技术实现学生信息管理系统。以下是该教程的完整攻略: 简介 在本教程的第一部分中,我们已经搭建好了项目的框架,包括所需的Java类和JSP页面。在本部分中,我们将添加更多的功能来实现完整的学生信息管理系统,并对代码进行相应的优化。 功能实现 添加学生信息 可以通过一个表单…

    Java 2023年5月24日
    00
  • Struts2在打包json格式的懒加载异常问题

    当使用Struts2进行json数据懒加载时,有可能会遇到打包json格式的异常问题。这种异常通常是由于Struts2缺少正确的json转换器或配置参数导致的。在本文中,将为您详细讲解如何解决这个问题。 1.检查json-lib库 首先要检查的事项是 json-lib 库, 您需要检查您项目中的 json-lib 包是否正常。 json-lib 库是 Str…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部