这个问题不知道咋解。想让用户在点击这个无权限的按钮时候提示他没有权限;我现在是在资源表配置 URL 的方式控制权限的。 万能的 V 友有了解 springSecurity 的吗。万分感谢额
1
src112159 OP 我在这个 URL 对应的方法上面加注解 @PreAuthorize("hasRole('ROLE_CO')") ,就能实现不跳转。直接返回 json
|
2
beny2mor 2018-11-17 14:19:12 +08:00
http.exceptionHandling()
.authenticationEntryPoint .accessDeniedHandler |
3
src112159 OP @beny2mor httpSecurity
.csrf().disable() .exceptionHandling() .authenticationEntryPoint(unauthorizedHandler) .accessDeniedHandler(myAccessDeniedHandler) 这个是有配置了的。 |
4
src112159 OP 也有没有权限的返回值 json。 但就是不知道它为啥还会跳转到登录页
|
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) // ``` |
6
beny2mor 2018-11-17 15:14:12 +08:00
@src112159
你的意思是你在数据库配置了用户-资源权限表,然后要这个表决策是吧。可以实现 AuthenticationProvider 注入 grands,然后用`accessDecisionManager`决策。 但其实这和手动写个 filter 差不多。 |
7
beny2mor 2018-11-17 15:19:42 +08:00
我好像理解错你的意思了?
你的登录页是指 security 的那个丑表单吗? 你是不是开启了 httpBasic |
8
src112159 OP 是跳转到了自定义的登录页。我现在就是在数据库配置了用户-资源权限表,用表里的资源来控制的
|
9
src112159 OP @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(); } |
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,但他自己也没怎么用过。。运行起来效果和我想的一样。。 |
12
beny2mor 2018-11-17 16:15:16 +08:00
![插入图片]( https://files.catbox.moe/4nve3e.jpg)
你没有设置 authenticationProvider 或 AccessDecisionManager,那么 authenticationEntryPoint 和 accessDeniedHandler 也不会生效。 你的代码好像就只有你有 filter 生效,并没有用到 security 的 Authentication 机制.... |
13
src112159 OP @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,现在就是会自己跳转到登录 |
15
src112159 OP 就是因为那个返回的 code 的原因,返回 1001 前段直接 logout 了。。。。
|
16
beny2mor 2018-11-17 16:48:12 +08:00
不知道惹。。
是完全没进入 AccessDecisionManager 吗。不过 AccessDecisionManager 好像需要先 setAuthenticated(true);才会进入。 |