java - Spring Boot 返回 403 虽然我有管理员权限

标签 java spring redirect spring-security jwt

我在添加 /admin 时想到了这个问题端点到 antMatchers("/admin").hasAuthority("ADMIN")它根本不会产生 获取 请求到 /admin并返回 200它返回 403反而
注:我使用 JWT 作为额外的身份验证层。
这是我的安全配置

httpSecurity.csrf().disable()
 .authorizeRequests().antMatchers("/", "/health", "/authority", "/dashboard", "/users/login", "/logoutUser", "/manageEvents", "/manageAeds", "/manageReports",
  "/charts", "/error", "/profile", "/authenticate/**", "/login", "/403", "/userProfile", "/deleteAed", "/users/add").permitAll()
 .antMatchers("/admin").hasAuthority("ADMIN")
 .antMatchers("/css/**", "/img/**", "/js/**", "/images/**", "/error_css/**", "/scss/**", "/vendor/**").permitAll()
 .anyRequest().authenticated().and().
exceptionHandling().accessDeniedPage("/403").and()
 .sessionManagement()
 .sessionCreationPolicy(SessionCreationPolicy.STATELESS);


httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

By moving it to permit.All() it will work but it's not the case here.


这是我处理内部重定向的地方 @Controller
@GetMapping("/authority")
public String getAuth(HttpServletResponse response) {

 if (jwt == null) {
  return "redirect:/login";
 }
 if (jwtTokenUtil.isTokenExpired(jwt)) {
  return "redirect:/login?token=expired";
 }
 response.addHeader("Auth", "Bearer " + jwt);

 System.out.println(loggedinUser.getRoles());

 if (loggedinUser != null) {
  if (loggedinUser.getRoles().equalsIgnoreCase("TILEFONITIS")) {
   return "redirect:/dashboard"; //will redirect
  } else if (loggedinUser.getRoles().equalsIgnoreCase("ADMIN")) {
   System.out.println("Admin");
   return "redirect:/admin"; //won't redirect
  } else if (loggedinUser.getRoles().equalsIgnoreCase("GUEST")) {
   return "redirect:/403"; // will redirect
  } else {
   return "redirect:/dashboard"; // will redirect
  }
 } else {
  return "redirect:/login";
 }

}
这是我的 /admin@Controller从来没有被调用过。
@GetMapping("/admin")
public String getAdmin(HttpServletResponse response) {
 if (jwt == null) {
  return "redirect:/login";
 }
 if (jwtTokenUtil.isTokenExpired(jwt)) {
  return "redirect:/login?token=expired";
 }
 response.addHeader("Auth", "Bearer " + jwt);

 System.out.println("jwt" + jwt);

 return "admin";

}

The odd thing is that with Postman i get redirected!


我在这里错过了什么?

编辑:第一个电话是在 /authenticate/web我在哪里告诉 Spring 我已通过身份验证
authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(auth.getUsername(), auth.getPassword()));

编辑2:
为了让事情更清楚:
来自 来访网站 , 流动:
  • 发帖 /authenticate/web
  • 使用 .js 重定向至 /authority (获取)
  • 不会重定向到 /admin (GET) -> 403

  • 来自 来访 postman , 流动:
  • 发帖 /authenticate/web
  • 获取 JWT并将其包含在标题中并对 /authority 进行 GET
  • 我看到了 管理员 模板。 -> 200

  • 这真的很奇怪,我添加了 jwt每次都用response.addHeader网站流动 。

    更新:
  • 这些是来自 postman 的响应头:

  • enter image description here
    加上 JWT .
  • 来自网络的响应 header

  • enter image description here
    虽然现在我注意到我得到 302 来自网络而不是 200
    正如你所看到的 admin页面是 403
    enter image description here

    更新 2:
    我设法打破了一些事情,
    首先
  • 通过拥有 httpSecurity.addFilterBefore关于我的安全
    配置意味着 spring 将寻找 JWT并在指定过滤器类的位置前添加过滤器
  • 权限已正确分配给用户,因此没有问题
    那里
  • 我改了 hasAuthority()hasRole()

  • 如果您收到 当前用户 您可以自动访问它的权限,如下所示
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    System.out.println("Principal: "+auth.getPrincipal());
    System.out.println("Authorities: "+auth.getAuthorities());             
    

    Because the authentication is overriden by the jwt filter this means i will only manage to get a user only if the request header contains the valid jwt


    这就是它从 postman 开始工作的原因但不是来自 web .

    另一个问题是,在我的 Controller 中,我试图添加 jwtresponse 只有当 Controller 完成它的工作时才会添加到它的标题中,我无法在下一行中获得用户主体,因为没有 jwt到它的请求 header 。
    此屏幕截图代表网络调用和来自 postman 的调用,两者均访问 /authority端点。
    enter image description here
  • 从 postman 你看到ADMIN作为权威
  • 但是从网上我有一个 ROLE_ANONYMOUS

  • 所以我有两个选择来解决这个问题:
  • 将其添加到请求 header 中。
  • 保护REST端点为 JWT并为 web 部件使用默认的 spring 安全(hasRole() 等)。
  • 最佳答案

    经过大量的反复试验,我设法分解了一些东西,并使用 JWT 使安全工作正常。以及默认 Spring 身份验证 .
    为了让它工作,我必须完全改变我的 SecurityConfig ,并将其更改为 MultipleSecurity .
    这是多重安全的工作原理:
    @Order(1)注释安全配置被标记为首先要查找的内容。

    @Order(1)
    @Configuration
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
     @Bean
     public AuthenticationManager authenticationManagerBean() throws Exception {
      return super.authenticationManagerBean();
     }
    
     @Override
     protected void configure(HttpSecurity httpSecurity) throws Exception {
      httpSecurity.csrf().disable()
       .antMatcher("/api/**").authorizeRequests()
       .antMatchers("/api/authenticate/android").permitAll()
       .anyRequest().authenticated().and()
       .exceptionHandling().accessDeniedPage("/403").and().sessionManagement()
       .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
       .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
     }
    
    }
    
  • @Order(1)智威汤逊
  • @Order(2)默认 Spring 安全

  • @Order(2)
    @Configuration
    public class SecurityConfiguration2 extends WebSecurityConfigurerAdapter {
    
     @Override
     protected void configure(HttpSecurity httpSecurity) throws Exception {
      httpSecurity.authorizeRequests()
       .antMatchers("/web/**").hasAuthority("ADMIN")
       .and().formLogin().defaultSuccessUrl("/redirect")
       .and().logout()
       .permitAll();
     }
    
    }
    
    我们基本上说这些配置是:
  • 寻找 JWT/api/**
  • /web/** 寻找权威

  • 所以所有的/web端点如 /web/admin现在需要 authorities而不是 JWT !
    以及来自 /api/** 的所有敏感信息将需要一个 JWT

    关于java - Spring Boot 返回 403 虽然我有管理员权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62426705/

    相关文章:

    python - subprocess.getstatusoutput(来自 Python 的旧命令.setstatusoutput())的多平台替代方案是什么?

    java - Java-无法播放某些Ogg剪辑

    java - 您的处理程序是否实现了像 Controller 这样受支持的接口(interface)?

    java - 具有不同消息选择器的多个 DefaultMessageListenerContainer 实例

    java - 无法使用比较器对 null 进行排序

    javascript - 使用 jQuery 的 Location header 在 POST 之后重定向

    java - 从 Java 程序操作 GIT 版本控制系统的输出

    java - 使用时钟 while 循环在 while 循环中读取文件

    java - Oracle 中的 jOOq MERGE

    java - 由 cron 调用时 Hadoop 作业失败