
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  你没有设置 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);才会进入。 |