聊聊 spring boot 后端大家如何玩权限? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shazh520
V2EX    Java

聊聊 spring boot 后端大家如何玩权限?

  •  
  •   shazh520 2019-12-13 14:41:24 +08:00 6830 次点击
    这是一个创建于 2188 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前后端完全分离那就 token 了,UUID 或者 jwt,这个我估计大家都这么做;

    但是前端渠道既有网页、APP 又有小程序,网页使用 thymeleaf 生成;这种情况下我用 spring security 就没法儿了,如果 token 的话,thymeleaf 这边就要憋屈一点,不能用 session,不用 token 的话 APP 和小程序又不行;

    嗯哼?

    26 条回复    2019-12-16 17:38:30 +08:00
    shazh520
        1
    shazh520  
    OP
       2019-12-13 14:45:05 +08:00
    因为我司前端技术储备不太够,所以前端除了 css 其他工作由我们几个后端来,有时候工期比较紧张的话就用 thymeleaf 了,不熟悉 webpack 的配置容易在上线的时候出点幺蛾子(半夜想睡的时候想 kill 人)
    zhenjiachen
        2
    zhenjiachen  
       2019-12-13 14:46:31 +08:00
    自定义 filter ,可以从 header 里面获取 token,也可以支持 session。或者直接所有的都使用 cookie,小程序和 app 应该都支持 cookie 的,引入 Spring Session 也支持分布式的。
    From313
        3
    From313  
       2019-12-13 14:48:03 +08:00
    @zhenjiachen ios 不支持 cookie
    manami
        4
    manami  
       2019-12-13 14:49:51 +08:00 via Android
    这种情况 redis 存 token 再适合不过了
    sutra
        5
    sutra  
       2019-12-13 14:51:24 +08:00
    我是自己实现了一个 HttpSessionIdResolver 来让 CookieHttpSessionIdResolver 和 HeaderHttpSessionIdResolver 自动选择:

    ```
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.springframework.http.MediaType;
    import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
    import org.springframework.security.web.util.matcher.OrRequestMatcher;
    import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
    import org.springframework.security.web.util.matcher.RequestMatcher;
    import org.springframework.session.web.http.CookieHttpSessionIdResolver;
    import org.springframework.session.web.http.HeaderHttpSessionIdResolver;
    import org.springframework.session.web.http.HttpSessionIdResolver;
    import org.springframework.web.accept.ContentNegotiationStrategy;

    public class SmartHttpSessionIdResolver implements HttpSessionIdResolver {

    protected final HttpSessionIdResolver browser;

    protected final HttpSessionIdResolver api;

    private final RequestMatcher browserMatcher;

    public SmartHttpSessionIdResolver(
    ContentNegotiationStrategy contentNegotiationStrategy) {
    this.browser = new CookieHttpSessionIdResolver();
    this.api = HeaderHttpSessionIdResolver.xAuthToken();

    MediaTypeRequestMatcher matcher = new MediaTypeRequestMatcher(
    contentNegotiationStrategy, Arrays.asList(MediaType.TEXT_HTML));
    matcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));

    RequestHeaderRequestMatcher Javascript = new RequestHeaderRequestMatcher(
    "X-Requested-With", "XMLHttpRequest");

    this.browserMatcher = new OrRequestMatcher(
    Arrays.asList(matcher, Javascript));
    }

    /**
    * {@inheritDoc}
    */
    @Override
    public List<String> resolveSessionIds(HttpServletRequest request) {
    return getResolver(request).resolveSessionIds(request);
    }

    /**
    * {@inheritDoc}
    */
    @Override
    pblic void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
    getResolver(request).setSessionId(request, response, sessionId);
    }

    /**
    * {@inheritDoc}
    */
    @Override
    public void expireSession(HttpServletRequest request, HttpServletResponse response) {
    getResolver(request).expireSession(request, response);
    }

    protected HttpSessionIdResolver getResolver(HttpServletRequest request) {
    return this.browserMatcher.matches(request) ? this.browser : this.api;
    }

    }
    ```
    zhenjiachen
        6
    zhenjiachen  
       2019-12-13 14:53:55 +08:00
    @From313 不可能吧,cookie 和 token 都是存在本地,然后请求的时候放在 header 里面啊,没有什么支不支持。把 cookie 当成 token 来用也是一样的。
    shazh520
        7
    shazh520  
    OP
       2019-12-13 14:56:48 +08:00
    @zhenjiachen 所说的不支持 cookie 应该是没有像浏览器这样方便,需要自己使用代码处理一下
    hiwind
        8
    hiwind  
       2019-12-13 15:00:44 +08:00
    用过 cookie 和 session,好像还是 cookie 用的多一些
    顺便想问问 前后端分离的情况下 前端页面 访问如何做权限管理
    meanhow
        9
    meanhow  
       2019-12-13 15:36:37 +08:00
    说道权限,顺道问一问各位数据权限该怎么做
    就是员工只能看自己处理的订单,经理可以看所有人的订单这样的
    琢磨了半天没什么头绪
    VensonEEE
        10
    VensonEEE  
       2019-12-13 15:52:36 +08:00
    脚手架都集成了 oauth2.0 吧,通用且方便集成,用就完了,熟了也快,少了很多选择的烦恼。
    权限,其实没有太好的办法,毕竟很多都是自由配置的。多套 service,自定义注解控制访问权限,避免提权攻击。
    lavvrence
        11
    lavvrence  
       2019-12-13 15:58:52 +08:00
    @dejavuwind token,请求头里携带
    lihongjie0209
        12
    lihongjie0209  
       2019-12-13 16:00:13 +08:00   1
    @meanhow #9 这是你的业务逻辑, 还是在业务代码中解决吧
    IGJacklove
        13
    IGJacklove  
       2019-12-13 16:01:52 +08:00
    @dejavuwind 后端做权限不就可以了?是否登录,用户类型,token 加 sql 基本都能解决吧,
    shazh520
        14
    shazh520  
    OP
       2019-12-13 16:13:03 +08:00   1
    @meanhow 思路就太多了;接口分开,经理一个,员工一个;一个接口的话判断用户权限,如果是员工的话查询条件加上员工 ID ;。。。
    cheng6563
        15
    cheng6563  
       2019-12-13 17:32:31 +08:00 via Android
    自己造轮子,spring security 真的是一言难尽
    a852695
        16
    a852695  
       2019-12-13 17:42:44 +08:00   1
    @meanhow 前端所有的权限包括路由都从后端接口获取
    ShutTheFu2kUP
        17
    ShutTheFu2kUP  
       2019-12-13 18:34:42 +08:00 via iPhone   1
    @meanhow 订单表加个员工 id,员工只查自己的 od 的订单,经理不带条件
    zhazi
        18
    zhazi  
       2019-12-13 19:52:31 +08:00 via Android
    spring security 可以支持 thymeleaf 和 restful 的
    hantsy
        19
    hantsy  
       2019-12-13 20:01:01 +08:00
    @shazh520 这个是框架安全上设计的考虑,与用不用 Spring Security 没太大关系。

    1. 如果 Web (Themleaf)页面 与 API 是一个程序,可以考虑多个 Spring Security Config,用 Order 排序。
    如:
    @Bean
    @Order(0)
    httpConfigbean 对应 pathMatcher("/web")使用常规 Web 设置。

    @Bean
    httpConfigbean 对应 pathMatcher("/api")使用 API 设置,可以无状态也可有状态与前者共享 Session.

    2. 如果纯后端 API,直接使用通用 API 安全方案。OAuth2,JWT,SpringSession 等。
    客户端( SPA,WebMVC/Themleaf,Mobile APP 等)交互都一样, 用相应的 Http Client 与 API 交互。

    从开发维护的角度,第二种比较也容易扩展。
    shazh520
        20
    shazh520  
    OP
       2019-12-13 20:41:02 +08:00
    @zhazi 都支持,但不同时支持,只能用其一
    shazh520
        21
    shazh520  
    OP
       2019-12-13 20:43:33 +08:00
    @hantsy 大佬能不能给个 demo 学一下
    meanhow
        22
    meanhow  
       2019-12-14 09:26:42 +08:00
    @shazh520 感谢回复。
    接口分开应该不行,因为至少会有老板,经理,员工三层,而且接口数量也挺多的
    不过我现在倒是有个想法,不知道能不能拦截所有 select,在角色表存一个数据权限的字段(个人,个人及部门),然后拦截所有 select,根据数据权限的字段在条件后面加上员工 ID
    meanhow
        23
    meanhow  
       2019-12-14 09:34:08 +08:00
    @ShutTheFu2kUP 实际情况会更复杂一点,至少有员工,部门经理,老板三层。
    倒是所有表都有创建人 id,可能要在查询上写上 in 条件吧
    optional
        24
    optional  
       2019-12-14 12:44:26 +08:00 via iPhone
    spring security 用起来太恶心,不如自己写几个 filter
    clancyliu
        25
    clancyliu  
       2019-12-14 14:15:18 +08:00
    oauth2,我们用的这个,网页,小程序,安卓三端
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3203 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 11:30 PVG 19:30 LAX 03:30 JFK 06:30
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86