对于想了解无法在SpringSecurity中使用@SecuredMethodSecurity批注的读者,本文将是一篇不可错过的文章,我们将详细介绍spring无法注入,并且为您提供关于@PreAut
对于想了解无法在Spring Security中使用@Secured Method Security批注的读者,本文将是一篇不可错过的文章,我们将详细介绍spring 无法注入,并且为您提供关于@PreAuthorize批注在Spring Security中不起作用、org.springframework.boot.autoconfigure.security.SecurityAuthorizeMode的实例源码、spring boot 整合spring security中spring security版本升级的遇到的坑、Spring security 5.0:spring security savedrequest 为空的有价值信息。
本文目录一览:- 无法在Spring Security中使用@Secured Method Security批注(spring 无法注入)
- @PreAuthorize批注在Spring Security中不起作用
- org.springframework.boot.autoconfigure.security.SecurityAuthorizeMode的实例源码
- spring boot 整合spring security中spring security版本升级的遇到的坑
- Spring security 5.0:spring security savedrequest 为空
无法在Spring Security中使用@Secured Method Security批注(spring 无法注入)
我做了很多研究,对我来说一切看起来都不错……但是我无法使它正常工作!有人知道吗?
不管我做什么,相关的映射对任何人都保持公开状态(无论匿名或登录,无论他们扮演什么角色)。
理想情况下,我希望所有请求都公开,但@Secured()注释的请求除外-显然,只有具有特定角色的用户才能访问这些映射。
那可能吗?
仅供参考,我目前构建了一种方法“ hasRole(String
role)”,该方法检查登录用户的角色,如果该方法返回false,则抛出NotAuthorizedException(定制)。
用户详细信息
@Override public Collection<? extends GrantedAuthority> getAuthorities() { List<GrantedAuthority> grantedAuthorities = null; System.out.print("Account role... "); System.out.println(account.getRole()); if (account.getRole().equals("USER")) { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER"); grantedAuthorities = Arrays.asList(grantedAuthority); } if (account.getRole().equals("ADMIN")) { GrantedAuthority grantedAuthorityUser = new SimpleGrantedAuthority("ROLE_USER"); GrantedAuthority grantedAuthorityAdmin = new SimpleGrantedAuthority("ROLE_ADMIN"); grantedAuthorities = Arrays.asList(grantedAuthorityUser, grantedAuthorityAdmin); } return grantedAuthorities; }
安全配置
@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(securedEnabled = true)public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private AuthFailure authFailure; @Autowired private AuthSuccess authSuccess; @Autowired private EntryPointUnauthorizedHandler unauthorizedHandler; @Autowired private UserDetailsServiceImpl userDetailsService; /*@Autowired public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception { builder.userDetailsService(userDetailsService); }*/ @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Autowired @Override public void configure(AuthenticationManagerBuilder builder) throws Exception { builder.userDetailsService(userDetailsService); } private CsrfTokenRepository csrfTokenRepository() { HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); repository.setHeaderName("X-XSRF-TOKEN"); return repository; } @Override public void configure(HttpSecurity http) throws Exception { http.csrf().csrfTokenRepository(csrfTokenRepository()) .and().exceptionHandling().authenticationEntryPoint(unauthorizedHandler) .and().formLogin().loginPage("/login").successHandler(authSuccess).failureHandler(authFailure) //.and().authorizeRequests().antMatchers("/rest/**").authenticated() //.and().authorizeRequests().antMatchers("/**").permitAll() .and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);; }
AccountController
@Secured("ROLE_USER") @RequestMapping(method = RequestMethod.GET) public List<Account> getAllAccounts(@RequestParam(value = "mail", required = false) String mail) {
谢谢!
答案1
小编典典您可以通过Spring HttpSecurity使用Controller范围的Security。尝试将其添加到您的configure方法中:
.antMatchers("rest/accounts*").hasRole("ADMIN")
如果您希望任何要求公开(真的吗?):
.anyRequest().permitAll()
当您从任何地方访问它时,还可以在UserDetailsService中保护示例的Methodinvocation:
@Secured("ROLE_USER")public getAllAccounts(...){...}
只有这样,您才需要使用以下方法注释SecurityConfig:
@EnableGlobalMethodSecurity(securedEnabled = true)
实际上,我们建议您在服务层使用方法安全性来控制对应用程序的访问,并且不要完全依赖于在Web应用程序级别定义的安全性约束的使用。URL会发生变化,很难考虑到应用程序可能支持的所有可能的URL以及如何处理请求。您应该尝试限制自己使用一些简单易懂的简单蚂蚁路径。始终尝试使用“默认拒绝”方法,在此方法中,您最后定义了一个全包通配符(/或),并拒绝访问。在服务层定义的安全性更健壮,更难绕开,因此您应始终利用Spring
Security的方法安全性选项。
参见:http :
//docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-
SNAPSHOT/reference/htmlsingle/#request-
matching
@PreAuthorize批注在Spring Security中不起作用
我发现了许多类似的问题,但都没有解决我的问题。我的问题是ROLE_USER
可以访问的功能ROLE_ADMIN
我的spring-security.xml代码如下。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<s:http auto-config="true" use-expressions="true">
<s:intercept-url pattern="/index.jsp" access="permitAll" />
<s:intercept-url pattern="/welcome*" access="hasRole('ROLE_USER')" />
<s:intercept-url pattern="/helloadmin*" access="hasRole('ROLE_ADMIN')" />
<s:form-login login-page="/login" default-target-url="/welcome"
authentication-failure-url="/loginfailed" />
<s:logout logout-success-url="/logout" />
</s:http>
<s:authentication-manager>
<s:authentication-provider>
<s:user-service>
<s:user name="asif" password="123456" authorities="ROLE_USER,ROLE_ADMIN" />
<s:user name="raheel" password="123456" authorities="ROLE_USER" />
</s:user-service>
</s:authentication-provider>
</s:authentication-manager>
当我添加<s:global-method-security pre-post-annotations="enabled"/>
我的代码时显示找不到资源错误,并且当我删除我的代码时成功执行但ROLE_USER
可以访问ROLE_ADMIN
函数
我的控制器功能是。
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value="/delete",method = RequestMethod.GET)
public String DeleteAll(ModelMap model,Principal principal ) {
org.springframework.security.core.userdetails.User activeUser = (org.springframework.security.core.userdetails.User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
System.out.println("Active user is "+activeUser.getUsername()+"Authorities are "+activeUser.getAuthorities());
return "deleteUsers";
}
org.springframework.boot.autoconfigure.security.SecurityAuthorizeMode的实例源码
@Override public void configure(HttpSecurity http) throws Exception { String path = this.console.getPath(); String antPattern = (path.endsWith("/") ? path + "**" : path + "/**"); HttpSecurity h2Console = http.antMatcher(antPattern); h2Console.csrf().disable(); h2Console.httpBasic(); h2Console.headers().frameOptions().sameOrigin(); String[] roles = this.security.getUser().getRole().toArray(new String[0]); SecurityAuthorizeMode mode = this.security.getBasic().getAuthorizeMode(); if (mode == null || mode == SecurityAuthorizeMode.ROLE) { http.authorizeRequests().anyRequest().hasAnyRole(roles); } else if (mode == SecurityAuthorizeMode.AUTHENTICATED) { http.authorizeRequests().anyRequest().authenticated(); } }
@Override public void configure(HttpSecurity http) throws Exception { String path = this.console.getPath(); String antPattern = (path.endsWith("/") ? path + "**" : path + "/**"); HttpSecurity h2Console = http.antMatcher(antPattern); h2Console.csrf().disable(); h2Console.httpBasic(); h2Console.headers().frameOptions().sameOrigin(); String[] roles = this.security.getUser().getRole().toArray(new String[0]); SecurityAuthorizeMode mode = this.security.getBasic().getAuthorizeMode(); if (mode == null || mode == SecurityAuthorizeMode.ROLE) { http.authorizeRequests().anyRequest().hasAnyRole(roles); } else if (mode == SecurityAuthorizeMode.AUTHENTICATED) { http.authorizeRequests().anyRequest().authenticated(); } }
@Override public void configure(HttpSecurity http) throws Exception { String path = this.console.getPath(); String antPattern = (path.endsWith("/") ? path + "**" : path + "/**"); HttpSecurity h2Console = http.antMatcher(antPattern); h2Console.csrf().disable(); h2Console.httpBasic(); h2Console.headers().frameOptions().sameOrigin(); String[] roles = this.security.getUser().getRole().toArray(new String[0]); SecurityAuthorizeMode mode = this.security.getBasic().getAuthorizeMode(); if (mode == null || mode == SecurityAuthorizeMode.ROLE) { http.authorizeRequests().anyRequest().hasAnyRole(roles); } else if (mode == SecurityAuthorizeMode.AUTHENTICATED) { http.authorizeRequests().anyRequest().authenticated(); } }
@Override public void configure(HttpSecurity http) throws Exception { String logoutSuccessUrl = buildUrl(casSecurityProperties.getServer().getBaseUrl(),casSecurityProperties.getServer().getPaths().getlogout()); http.logout().permitAll().logoutSuccessUrl(logoutSuccessUrl); SecurityAuthorizeMode mode = casSecurityProperties.getAuthorizeMode(); if (mode == SecurityAuthorizeMode.ROLE) { List<String> roles = securityProperties.getUser().getRole(); http.authorizeRequests().anyRequest().hasAnyRole(roles.toArray(new String[roles.size()])); } else if (mode == SecurityAuthorizeMode.AUTHENTICATED) { http.authorizeRequests().anyRequest().authenticated(); } }
spring boot 整合spring security中spring security版本升级的遇到的坑
在spring security3.x的版本中
hasAnyRole这个方法不会对我们需要认证的身份前面加个前缀ROLE_,在3.x版本hasRole的源码如下
public final boolean hasAnyRole(String... roles) {
Set<String> roleSet = getAuthoritySet();
for (String role : roles) {
if (roleSet.contains(role)) {
return true;
}
}
return false;
}
而4.x版本下的会根据我的具体情况看看是不是要加前缀,代码如下
public final boolean hasAnyRole(String... roles) {
return hasAnyAuthorityName(defaultRolePrefix, roles);
}
private boolean hasAnyAuthorityName(String prefix, String... roles) {
Set<String> roleSet = getAuthoritySet();
for (String role : roles) {
String defaultedRole = getRoleWithDefaultPrefix(prefix, role);
if (roleSet.contains(defaultedRole)) {
return true;
}
}
return false;
}
private static String getRoleWithDefaultPrefix(String defaultRolePrefix, String role) {
if (role == null) {
return role;
}
if (defaultRolePrefix == null || defaultRolePrefix.length() == 0) {
return role;
}
if (role.startsWith(defaultRolePrefix)) {
return role;
}
return defaultRolePrefix + role;
}
这里的这个坑要小心,如果加了Role_前缀,那么你登录时的角色的前面也需要加Role_才行,不然会认证失败,然后就是403页面了。(ps:hasRole这个方法也有这个版本问题,具体也是和hasAnyRole差不多。)
Spring security 5.0:spring security savedrequest 为空
如何解决Spring security 5.0:spring security savedrequest 为空?
我有一个 spring boot 客户端应用程序,我在其中使用 spring-boot-starter-oauth2-client 和 spring-boot-starter-security。同一个应用程序在一个环境中运行良好,但是在另一个环境中部署后,我可以看到 spring security 保存的请求为空,这就是它不断重定向到登录页面的原因。
启用 spring 安全调试日志后,我可以看到身份验证成功并检索到用户详细信息。但是,它继续重定向到“/”,因为spring security 保存的请求为空。
我不知道问题出在哪里,为什么它能够在一种环境中而不是在另一种环境中保存请求。我应该从哪里开始寻找?任何帮助将不胜感激。
应用程序未重定向的调试日志
{"timestamp":"2021-05-12T17:24:40.918+10:00","app":"my-protected-application","logLevel":"INFO","thread":"http-nio-8080-exec-1","eventSource":"org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/]","message":"Initializing Spring dispatcherServlet ''dispatcherServlet''"}
{"timestamp":"2021-05-12T17:24:41.104+10:00","traceId":"2efe5d4e6d04f787","spanId":"2efe5d4e6d04f787","logLevel":"DEBUG","eventSource":"org.springframework.security.web.util.matcher.AntPathRequestMatcher","message":"Checking match of request : ''/actuator/health/readiness''; against ''/actuator/info''"}
{"timestamp":"2021-05-12T17:24:41.112+10:00","message":"Checking match of request : ''/actuator/health/readiness''; against ''/actuator/health/readiness''"}
{"timestamp":"2021-05-12T17:24:41.112+10:00","eventSource":"org.springframework.security.web.FilterChainProxy","message":"/actuator/health/readiness has an empty filter list"}
{"timestamp":"2021-05-12T17:24:55.666+10:00","traceId":"9681ad4d267d4beb","spanId":"9681ad4d267d4beb","thread":"http-nio-8080-exec-2","message":"Checking match of request : ''/oauth2/authorization/my-protected-application''; against ''/actuator/info''"}
{"timestamp":"2021-05-12T17:24:55.666+10:00","message":"Checking match of request : ''/oauth2/authorization/my-protected-application''; against ''/actuator/health/readiness''"}
{"timestamp":"2021-05-12T17:24:55.666+10:00","message":"Checking match of request : ''/oauth2/authorization/my-protected-application''; against ''/actuator/health/liveness''"}
{"timestamp":"2021-05-12T17:24:55.668+10:00","message":"/oauth2/authorization/my-protected-application at position 1 of 14 in additional filter chain; firing Filter: ''WebAsyncManagerIntegrationFilter''"}
{"timestamp":"2021-05-12T17:24:55.670+10:00","message":"/oauth2/authorization/my-protected-application at position 2 of 14 in additional filter chain; firing Filter: ''SecurityContextPersistenceFilter''"}
{"timestamp":"2021-05-12T17:24:55.670+10:00","eventSource":"org.springframework.security.web.context.HttpSessionSecurityContextRepository","message":"No HttpSession currently exists"}
{"timestamp":"2021-05-12T17:24:55.670+10:00","message":"No SecurityContext was available from the HttpSession: null. A new one will be created."}
{"timestamp":"2021-05-12T17:24:55.673+10:00","message":"/oauth2/authorization/my-protected-application at position 3 of 14 in additional filter chain; firing Filter: ''HeaderWriterFilter''"}
{"timestamp":"2021-05-12T17:24:55.674+10:00","message":"/oauth2/authorization/my-protected-application at position 4 of 14 in additional filter chain; firing Filter: ''logoutFilter''"}
{"timestamp":"2021-05-12T17:24:55.674+10:00","eventSource":"org.springframework.security.web.util.matcher.OrRequestMatcher","message":"Trying to match using Ant [pattern=''/logout'',GET]"}
{"timestamp":"2021-05-12T17:24:55.675+10:00","message":"Checking match of request : ''/oauth2/authorization/my-protected-application''; against ''/logout''"}
{"timestamp":"2021-05-12T17:24:55.675+10:00",POST]"}
{"timestamp":"2021-05-12T17:24:55.675+10:00","message":"Request ''GET /oauth2/authorization/my-protected-application'' doesn''t match ''POST /logout''"}
{"timestamp":"2021-05-12T17:24:55.675+10:00",PUT]"}
{"timestamp":"2021-05-12T17:24:55.675+10:00","message":"Request ''GET /oauth2/authorization/my-protected-application'' doesn''t match ''PUT /logout''"}
{"timestamp":"2021-05-12T17:24:55.675+10:00",DELETE]"}
{"timestamp":"2021-05-12T17:24:55.675+10:00","message":"Request ''GET /oauth2/authorization/my-protected-application'' doesn''t match ''DELETE /logout''"}
{"timestamp":"2021-05-12T17:24:55.675+10:00","message":"No matches found"}
{"timestamp":"2021-05-12T17:24:55.676+10:00","message":"/oauth2/authorization/my-protected-application at position 5 of 14 in additional filter chain; firing Filter: ''OAuth2AuthorizationRequestRedirectFilter''"}
{"timestamp":"2021-05-12T17:24:55.676+10:00","message":"Checking match of request : ''/oauth2/authorization/my-protected-application''; against ''/oauth2/authorization/{registrationId}''"}
{"timestamp":"2021-05-12T17:24:55.676+10:00","message":"Checking match of request : ''/oauth2/authorization/my-protected-application''; against ''/oauth2/authorization/{registrationId}''"}
解决方法
您是直接调用登录 URL 而不是尝试通过登录页面登录吗?
用户请求的请求数据存储在 requestCache
中。
此处存储的请求数据为 savedRequest
。
Spring security
在用户身份验证后重定向 requestCache
和 savedRequest
对象。
SavedRequest
必须为空,因为如果不使用登录页面直接使用 URL,则前一个请求中没有请求数据。
您可以尝试从登录页面登录或使用 Referrer
标头获取页面 URL。
我们今天的关于无法在Spring Security中使用@Secured Method Security批注和spring 无法注入的分享就到这里,谢谢您的阅读,如果想了解更多关于@PreAuthorize批注在Spring Security中不起作用、org.springframework.boot.autoconfigure.security.SecurityAuthorizeMode的实例源码、spring boot 整合spring security中spring security版本升级的遇到的坑、Spring security 5.0:spring security savedrequest 为空的相关信息,可以在本站进行搜索。
本文标签: