Spring 方法安全导致自动装配对象的空值

Spring Method Security causes Null values for autowired objects

我玩过 spring 证券方法安全性,但出现了一个非常奇怪的行为。我有几个控制器 classes,方法用 @PreAuthorize 注释以限制某些用户角色的访问。

有一个控制器Class在添加方法安全性后注入的对象为空。我调试了我的代码并发现了以下内容:

serviceuserService是注入对象

@Controller
public class OrderController {

    @Autowired
    private OrderService service;

    @Autowired
    private UserService userService;

我觉得奇怪的是this的值描述:OrderController$$EnhancerBySpringCGLIB$$1a7122f6。通过删除所有 MethodSecurity 注释,class 按预期工作。

当我查看其他也使用方法安全性的控制器 Classes 时,它们工作正常并且调试器中的变量列表看起来正常:

@Controller
public class UserController {

    @Autowired
    private UserService service;

我还搜索了我可能用注释造成的错误,但 OrderController 中的注释看起来与其他控制器中的注释相同 classes。这里的 OrderController 示例 Class:

@Controller
public class OrderController {
              .
              .
              .
    @GetMapping("/dispo/dispo")
    @PreAuthorize("hasAuthority('ADMIN') or hasAuthority('DISPATCH')")
    private String showDispoPage() {
        return "/dispo/dispo";
    }

    @GetMapping("/dispo/orderCreate")
    @PreAuthorize("hasAuthority('ADMIN') or hasAuthority('AL_SYNC_ADMIN') or hasAuthority('CLIENT_USER') or hasAuthority('DISPATCH')")
    private String showCreateOrder(Model model) {
        List<MdUser> userList = service.getUsers();
        model.addAttribute("userList", userList);

        return "/dispo/orderCreate";
    }
}

这里是另一个按预期工作的控制器 Class 的示例:

@Controller
public class UserController {
                 .
                 .
                 .

    @GetMapping("/admin/user")
    @PreAuthorize("hasAuthority('ADMIN') or hasAuthority('DISPATCH') or hasAuthority('WEBTOOL_USER')")
    public String showInvalidUserPage(Model model) {
        List<UserModel> invalidUserList = service.findInvalidUsers(service.getUsers());

        model.addAttribute("userList", invalidUserList);
        return "/admin/user";
    }

    @GetMapping("/admin/userCreate")
    @PreAuthorize("hasAuthority('ADMIN')")
    public String showNewUserPage(Model model) {
        UserModel user = new UserModel();
        model.addAttribute("user", user);
        return "/admin/userCreate";
    }
}

那么这里可能出了什么问题?我不明白为什么这个 class 与另一个 class 有不同的行为。

Spring 安全性使用 AOP(面向方面​​的编程)"wrap" 带有 AOP 建议的注释方法。一旦调用带有 pre/post 安全注释的方法,建议就会检查用户是否经过身份验证和授权。验证成功则调用该方法,否则遍历unauthorized/unauthenticed个流程

Spring AOP 只能在public 方法上执行runtime 织入。 showDispoPageshowCreateOrder 都是私有的,这可能会干扰安全建议。

我会将 pre/post 授权注释移动到服务层。它不仅在控制器注解和安全注解之间提供了更好的分离,而且还可以防止将来出现任何错误。例如,在您当前的设置中,如果通过已忘记安全注释的不同控制器调用对 UserService 方法的任何调用,则不会对其进行验证。

此外,您还可以选择使用 web security(保护对 URI 的访问,例如保护 /some/path)以及当前的 method level security 设置。

对于 Kotlin 用户,确保方法不是最终的

浪费了两天。