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

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

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

    前后端完全分离那就 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
    public 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 应该是没有像浏览器这样方便,需要自己使用代码处理一下
    dejavuwind
        8
    dejavuwind  
       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,自定义注解控制访问权限,避免提权攻击。
    jaylee4869
        11
    jaylee4869  
       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   ·   实用小工具   ·   3525 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:59 · PVG 18:59 · LAX 02:59 · JFK 05:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.