java - 尽管我有管理员权限,但 Spring Boot 返回 403
问题描述
/admin
当我向它添加端点时,我遇到了这个问题antMatchers("/admin").hasAuthority("ADMIN")
,根本不会发出GET请求/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);
通过将其移至
permit.All()
它会起作用,但这里并非如此。
这是我在里面处理重定向的地方@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";
}
奇怪的是,使用Postman ,我被重定向了!
我在这里想念什么?
编辑:第一个电话是在/authenticate/web
我告诉春天我已通过身份验证的地方
authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(auth.getUsername(), auth.getPassword()));
编辑2:
为了让事情更清楚:
网络访问,流程:
- 邮政
/authenticate/web
- 重定向
.js
到/authority
(GET) - 不会重定向到
/admin
(GET) -> 403
Postman来访,流程:
- 邮政
/authenticate/web
- 获取
JWT
并将其包含在标题中并进行 GET 到/authority
- 我看到了管理模板。-> 200
这真的很奇怪,我jwt
每次都response.addHeader
在网络流上添加。
更新:
- 这些是邮递员的响应标头:
加上JWT
.
- 来自网络的响应标头
虽然现在我注意到我从网上得到302而不是200
如您所见,admin
页面是403
更新 2:
我已经设法分解了一些东西,首先
通过
httpSecurity.addFilterBefore
我的安全配置意味着 spring 将JWT
在指定过滤器类的位置之前查找并添加一个过滤器权限已正确分配给用户,因此没有问题
hasAuthority()
我改成hasRole()
如果您获得当前用户,您可以自动访问它的权限,如下所示
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
System.out.println("Principal: "+auth.getPrincipal());
System.out.println("Authorities: "+auth.getAuthorities());
因为
authentication
被覆盖了jwt filter
这意味着我只有在请求标头包含有效的情况下才能设法获取用户jwt
这就是为什么它postman
从web
.
另一个问题是,在我的控制器中,我试图添加标题,只有当控制器完成它的工作时才会添加到标题中,我无法进入用户主体的下一行,因为jwt
它没有请求标头。response
jwt
此屏幕截图表示网络呼叫和来自邮递员的呼叫,两者都访问/authority
端点。
- 从邮递员那里,您将
ADMIN
其视为权威 - 但是从网上我有一个
ROLE_ANONYMOUS
所以我有两个选择来解决这个问题:
- 将其添加到请求标头中。
- 使用 Web 部件的默认 spring 安全性(等)保护
REST
端点。JWT
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)
默认弹簧安全
@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
推荐阅读
- python - 如何找到 teradataml 包的版本?
- groovy - 使用groovy从表中获取数据并存储到变量中?
- javascript - 导入后 JavaScript 无法识别代码
- oracle - Oracle Apex:上传向导 -> 将 Apex_Collections 错误表导出到 CSV 文件会阻止页面的其余部分呈现
- ios - “使用 Apple 登录”是否允许应用向后兼容 iOS 12 及更低版本?
- php - Wordpress 一页网站使用 wp_is_mobile() 加载缓慢
- c# - 如何在 Unity 中使用力来校正角加速度
- gitlab - 托管 Gitlab:在 ~/public 页面上编辑预设文本
- typescript - 访问包含函数的初始化内部的类型属性
- php - Laravel 通过具有价值的中间表关联 2 个模型