V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
CingFuture
V2EX  ›  Java

请教大家一个关于 spring security 鉴权的问题

  •  
  •   CingFuture · 144 天前 · 1863 次点击
    这是一个创建于 144 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想将一个方法中权限验证与业务尽可能地解耦

    例如下面这样一个方法

    deleteDocument(String docId) { ... }

    通过 docId 查找数据库中的 document 表,确认其中的 owner 是否是当前登录用户。 如果:1.是当前登录用户 2.不是当前登录用户,但当前登录用户是管理员 即判断有删除文档的权限,之后就进行纯粹的业务逻辑的代码。

    请问上述操作 spring security 有实现的办法吗。或者说有其他的方法可以实现?谢谢大家!

    23 条回复    2021-06-04 09:24:35 +08:00
    liuxu
        1
    liuxu   144 天前
    phper 用 laravel 就不会提出这种问题
    Cbdy
        2
    Cbdy   144 天前 via Android
    Spring Security 是人间之屑,建议别用

    你这种需求一个拦截器就完事儿了,比如这种

    https://github.com/cbdyzj/natrium/blob/master/common/src/main/java/nano/support/validation/ValidateInterceptor.java
    Hugg
        3
    Hugg   144 天前 via Android
    securityContextHolder 可以获取当前用户信息,做下 if else 即可
    Huiao
        4
    Huiao   144 天前
    换个思路,是否可以加个 mybatis 插件在删除语句后面拼接 sql 判断 owner 是否是当前用户
    Hugg
        5
    Hugg   144 天前 via Android
    或者你在 controller 加上 Authentication 参数
    guxingke
        6
    guxingke   144 天前   ❤️ 1
    PostAuthorize 注解 + SPEL 可解

    =====
    @PostAuthorize("returnObject.owner == authentication.id")
    Doc findOwnerDoc(String docId);
    xuanbg
        7
    xuanbg   144 天前   ❤️ 2
    spring security 把很多人带沟里去了。。。明明可以很简单的鉴权,上了 spring security 后就变得很复杂。
    jorneyr
        8
    jorneyr   144 天前   ❤️ 2
    通过 docId 查找数据库中的 document 表:
    这个已经属于业务逻辑级别了,得查询数据库,不是框架级能够处理的。甚至不同业务表的数据 owner 字段名都不一样,有的用 user_id, 有的用 owner_id,有的用 creator_id 都可能,是千变万化的,不同的请求查询的表也不同,框架提供的权限判断只是 permission 和 role 级别的,数据级的没看到过。
    jorneyr
        9
    jorneyr   144 天前
    当然自定义注解,实现查询指定的表和字段以及匹配的值和相关权限,在执行方法前先通过注解进行处理,判断是否有足够的权限也是可以做到,但这不是 spring security 自带的功能。
    CingFuture
        10
    CingFuture   144 天前
    谢谢各位的回答,我好好消化一下!
    fpure
        11
    fpure   144 天前
    我反正只把 spring security 当过滤器用,完全不用它的权限之类的,这样还是挺好用的
    lybcyd
        12
    lybcyd   144 天前   ❤️ 1
    https://docs.spring.io/spring-security/site/docs/current/reference/html5/#el-pre-post-annotations

    文档就可以解答你的疑惑,启用注解鉴权后,直接利用注解搞定
    xianzhe
        13
    xianzhe   144 天前   ❤️ 1
    ```
    @DeleteMapping("/{id}")
    @PreAuthorize("#Id == null || @documentService.hasDeletePermission(#Id)")
    public ResponseEntity<?> getGlobalAlertList(@RequestParam String Id){
    }
    ```
    xianzhe
        14
    xianzhe   144 天前
    大概这样子写,很方便
    SuperXRay
        15
    SuperXRay   144 天前
    我也有个问题
    spring security 如何无密码授权?
    lostSoul
        16
    lostSoul   144 天前
    @SuperXRay 我当初也遇到这个问题 授权微信小程序登录 但是微信小程序并没有密码这个玩意 我最后是自己重写了 provider 类 不走 passwordEncoder 这个东西就行了
    lostSoul
        17
    lostSoul   144 天前   ❤️ 1
    @SuperXRay springSecurity 自带的 DaoAuthenticationProvider 会 调用注入的 passwordEncoder 你只要自己写个类 覆盖下 DaoAuthenticationProvider 的 authenticate 方法调用了 additionalAuthenticationChecks 这个方法 你可以复写掉 authenticate 这个方法 直接调用 service 就行了 我当初为了这个 把 security 的源码和文档看了三天调试了三天
    lostSoul
        18
    lostSoul   144 天前
    网上一直吐槽 security 太重了 但是其实真正去看了 security 的源码你会学到很多骚操作新思想 不过不可否认他确实过度设计了
    mikulch
        19
    mikulch   144 天前
    @guxingke
    @lostSoul

    不知道两位是否遇到过使用 SpEL + PreAuthrorize 自定义权限校验逻辑的时候,框架抛出的 AccessdeniedException 异常,无法被 ExceptionTranslater 异常处理拦截器处理的情况没有?

    看 debug 的过程,就是当权限投票失败处理以后,正常抛出了 AccessdeniedException,但是这个没有向上一直抛到 ExceptionTranslater,而是莫名其妙直接到了 DispatchServlet 然后被处理打印到控制台,然后程序返回到 ExceptionTranslater 以后直接就没有异常了的情况?
    tamer
        20
    tamer   144 天前
    但凡看过一遍官方文档,也不会说出过度设计,故意复杂化这种话.
    JamesMackerel
        21
    JamesMackerel   143 天前 via iPhone
    看到有人在这里劝退我就放心了。
    SuperXRay
        22
    SuperXRay   143 天前
    @lostSoul 感谢,这个问题确实困扰我挺久
    litchinn
        23
    litchinn   142 天前
    方法级别的权限,我赞同 13 楼,我也是这么用的
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1170 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 18:16 · PVG 02:16 · LAX 11:16 · JFK 14:16
    ♥ Do have faith in what you're doing.