用 springSecurity 登录状态下点击无权限的 URL 按钮直接跳转到登录页? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
src112159
V2EX    Java

用 springSecurity 登录状态下点击无权限的 URL 按钮直接跳转到登录页?

  •  
  •   src112159 2018-11-17 13:09:43 +08:00 3895 次点击
    这是一个创建于 2570 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这个问题不知道咋解。想让用户在点击这个无权限的按钮时候提示他没有权限;我现在是在资源表配置 URL 的方式控制权限的。 万能的 V 友有了解 springSecurity 的吗。万分感谢额

    src112159
        1
    src112159  
    OP
       2018-11-17 13:59:47 +08:00
    我在这个 URL 对应的方法上面加注解 @PreAuthorize("hasRole('ROLE_CO')") ,就能实现不跳转。直接返回 json
    beny2mor
        2
    beny2mor  
       2018-11-17 14:19:12 +08:00
    http.exceptionHandling()
    .authenticationEntryPoint
    .accessDeniedHandler
    src112159
        3
    src112159  
    OP
       2018-11-17 14:54:36 +08:00
    @beny2mor httpSecurity
    .csrf().disable()

    .exceptionHandling()
    .authenticationEntryPoint(unauthorizedHandler)
    .accessDeniedHandler(myAccessDeniedHandler)

    这个是有配置了的。
    src112159
        4
    src112159  
    OP
       2018-11-17 14:59:29 +08:00
    也有没有权限的返回值 json。 但就是不知道它为啥还会跳转到登录页
    johnniang
        5
    johnniang  
       2018-11-17 15:04:44 +08:00
    ```

    @Override
    public void configure(HttpSecurity http) throws Exception {
    http //
    .apply(validateCodeSecurityConfig) //
    .and() //
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //

    .and() //
    .formLogin().permitAll() //
    .loginProcessingUrl("/api/v1/auth/login") //
    .successHandler(authenticationSuccessHandler) //
    .failureHandler(authenticationFailureHandler) //

    ```
    beny2mor
        6
    beny2mor  
       2018-11-17 15:14:12 +08:00
    @src112159
    你的意思是你在数据库配置了用户-资源权限表,然后要这个表决策是吧。可以实现 AuthenticationProvider 注入 grands,然后用`accessDecisionManager`决策。
    但其实这和手动写个 filter 差不多。
    beny2mor
        7
    beny2mor  
       2018-11-17 15:19:42 +08:00
    我好像理解错你的意思了?

    你的登录页是指 security 的那个丑表单吗?
    你是不是开启了 httpBasic
    src112159
        8
    src112159  
    OP
       2018-11-17 15:29:26 +08:00
    是跳转到了自定义的登录页。我现在就是在数据库配置了用户-资源权限表,用表里的资源来控制的
    src112159
        9
    src112159  
    OP
       2018-11-17 15:33:03 +08:00
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
    // 由于使用的是 JWT,我们这里不需要 csrf
    .csrf().disable()

    .exceptionHandling()
    .accessDeniedHandler(myAccessDeniedHandler)
    .authenticationEntryPoint(unauthorizedHandler)
    .and()

    // 基于 token,所以不需要 session
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

    .authorizeRequests()

    // 允许对于网站静态资源的无授权访问
    .antMatchers(
    HttpMethod.GET,
    "/",
    "/*.html",
    "/favicon.ico",
    "/**/*.html",
    "/**/*.css",
    "/**/*.js",
    "/**/*.png",
    "/**/*.jpg"
    ).permitAll()
    // 对于获取 token 的 rest api 要允许匿名访问
    .antMatchers("/api/auth/**").permitAll()
    .antMatchers("/sys_user/**").permitAll()
    .antMatchers("/x_mgr/**/*.*").permitAll()
    // 除上面外的所有请求全部需要鉴权认证
    .anyRequest().authenticated();

    // 添加 JWT filter
    httpSecurity
    .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
    httpSecurity.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
    // 禁用缓存
    httpSecurity.headers().cacheControl();
    }
    src112159
        10
    src112159  
    OP
       2018-11-17 15:52:50 +08:00
    @beny2mor 这样权限控制好像是没有问题的,但就是会跳转到自定义的登录页面
    beny2mor
        11
    beny2mor  
       2018-11-17 16:13:00 +08:00
    @src112159

    你是没进入`myAccessDeniedHandler`而是进入了`unauthorizedHandler`吗。。

    我对 security 的理解是这样的:

    用户认证失败会进入 authenticationEntryPoint 用户认证失败指是的账号、密码对不上,或者 token 找不到用户之类的; 然后这一步是在`authenticationProvider`配置中发生的,如果配置的 AuthenticationProvider 返回 null 就是认证失败,返回 AbstractAuthenticationToken 则是通过。

    用户没有权限会进入 accessDeniedHandler, 用户没权限是指能从 token 或账号密码找到用户,但是没有通过权限认证,比如#1 的 @PreAuthorize("hasRole('ROLE_CO')")注解; 这一步是在 accessDecisionManager 配置的,这里可能是一组 Voter。

    filter 失败会进入会在 filter 中直接写错误的返回(`res.setStatus(403)`之类的)。

    https://files.catbox.moe/4nve3e.jpg
    先后顺序是: 先进入 filter,filter 的作用是设置简单的 Authentication ; 然后进入 authenticationProvider,这一步是判断用户是否合法,并补全 Authentication 信息;最后进入 AccessDecisionManager,这一步会根据补全的 Authentication 判断是否有权限。



    我是看了一大堆的文章自己理解的,领导让我用 security,但他自己也没怎么用过。。运行起来效果和我想的一样。。
    beny2mor
        12
    beny2mor  
       2018-11-17 16:15:16 +08:00
    ![插入图片]( https://files.catbox.moe/4nve3e.jpg)

    你没有设置 authenticationProvider 或 AccessDecisionManager,那么 authenticationEntryPoint 和 accessDeniedHandler 也不会生效。 你的代码好像就只有你有 filter 生效,并没有用到 security 的 Authentication 机制....
    src112159
        13
    src112159  
    OP
       2018-11-17 16:36:10 +08:00
    @beny2mor
    @Service
    public class MyAccessDecisionManager implements AccessDecisionManager {


    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
    if(null == configAttributes || configAttributes.size() <= 0) {
    return;
    }
    ConfigAttribute c;
    String needRole;
    for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {
    c = iter.next();
    needRole = c.getAttribute();
    for(GrantedAuthority ga : authentication.getAuthorities()) {
    if(needRole.trim().equals(ga.getAuthority())) {
    return;
    }
    }
    }
    throw new AccessDeniedException("没有操作权限");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
    return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
    return true;
    }
    }


    ----------------------------------------------------------------


    @Component
    public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
    //返回 json 形式的错误信息
    response.setCharacterEncoding("UTF-8");
    response.setContentType("application/json");
    response.getWriter().println("{\"code\":1001, \"msg\":\""+e.getMessage()+"\"}");
    response.getWriter().flush();
    }
    }


    ----------------------------------------------------------
    是有 AccessDecisionManager 的,无权限的资源也返回了这个 json,现在就是会自己跳转到登录
    src112159
        14
    src112159  
    OP
       2018-11-17 16:44:57 +08:00
    @beny2mor

    已经找到问题了,谢谢你的帮助哈,。
    src112159
        15
    src112159  
    OP
       2018-11-17 16:46:12 +08:00
    就是因为那个返回的 code 的原因,返回 1001 前段直接 logout 了。。。。
    beny2mor
        16
    beny2mor  
       2018-11-17 16:48:12 +08:00
    不知道惹。。

    是完全没进入 AccessDecisionManager 吗。不过 AccessDecisionManager 好像需要先 setAuthenticated(true);才会进入。
    beny2mor
        17
    beny2mor  
       2018-11-17 16:49:15 +08:00
    @src112159 #15 啥, 哪里 logout 了
    beny2mor
        18
    beny2mor  
       2018-11-17 17:00:11 +08:00
    @beny2mor 好吧,前端退出。。。
    security 也可以写测试的吧
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2839 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 13:48 PVG 21:48 LAX 05:48 JFK 08:48
    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