具有角色的经过身份验证的用户的 Spring Security Java 配置
Posted
技术标签:
【中文标题】具有角色的经过身份验证的用户的 Spring Security Java 配置【英文标题】:Spring Security Java configuration for authenticated users with a role 【发布时间】:2016-02-13 21:17:18 【问题描述】:我正在尝试使用带有 Spring Boot 的 Java 配置来配置 Spring Security。
我的 WebSecurityConfig 类有一个这样的配置方法
@Override
protected void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
.antMatchers("/", "/login", "/css/**", "/js/**", "/img/**", "/bootstrap/**" ).permitAll()
.antMatchers("/individual", "/application", "/upload").hasRole("USER")
.and()
.formLogin()
.loginPage("/login")
.successHandler(successHandler);
我为未经身份验证的用户获得了登录页面,并且用户进行了身份验证。但是,当尝试访问 url /individual 时,我收到 403 错误,并且在日志中
2015-11-12 13:59:46.373 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/individual'; against '/'
2015-11-12 13:59:46.373 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/individual'; against '/login'
2015-11-12 13:59:46.373 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/individual'; against '/css/**'
2015-11-12 13:59:46.373 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/individual'; against '/js/**'
2015-11-12 13:59:46.374 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/individual'; against '/img/**'
2015-11-12 13:59:46.374 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/individual'; against '/bootstrap/**'
2015-11-12 13:59:46.374 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/individual'; against '/individual'
2015-11-12 13:59:46.374 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /individual; Attributes: [hasRole('ROLE_USER')]
2015-11-12 13:59:46.374 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@4c2eda81: Principal: org.springframework.security.core.userdetails.User@4c0ab982: Username: foo@bar.com; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffc7f0c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 6E0BF830C070912EAC0050D1285D5CF9; Granted Authorities: USER
2015-11-12 13:59:46.374 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@6f192fd7, returned: -1
2015-11-12 13:59:46.386 DEBUG 34468 --- [nio-8090-exec-6] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is not anonymous); delegating to AccessDeniedHandler
如果我将.hasRole("USER")
替换为.authenticated()
,它会起作用并且用户会获得所需的页面,但不会检查任何角色。
我不知道如何指定用户必须经过身份验证并具有角色 USER。我查看了许多示例并尝试了许多组合,但我无法让它按预期工作。大多数示例还引用了较旧的基于 XML 的配置,我想避免这种情况。
我需要做什么来指定某些 URL 模式可以由具有某些角色的经过身份验证的用户访问?
根据要求,成功处理程序方法如下所示
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth)
throws IOException, ServletException
// Here we want to check whether the user has already started the process and redirect to the appropriate stage
log.info("User has been authenticated", auth.getName());
if(auth.getName().equals("foo@bar.com"))
redirectStrategy.sendRedirect(request, response, "/individual");
return;
redirectStrategy.sendRedirect(request, response, "/application");
请注意,根据代码中的 cmets,这是早期 WIP。我知道这是有效的,因为出现了日志消息,并且没有在 WebSecurity 类中进行角色检查,就会提供所需的页面。
编辑:注意到在提到 roleService.getDefaultRole() 的问题中有一个错字。这是一个错误,已更正。
【问题讨论】:
不要将角色指定为 USER,而应指定为 ROLE_USER。 查看下面的答案并发表评论,这会导致配置异常 显示您在用户登录时为用户分配角色的代码。 日志输出显示用户对象具有授予权限USER,所以我知道它正在分配给用户 根据我的回答,要么需要将 ROLE_USER 分配给 foo@bar.com,要么检查hasAuthority
而不是 hasRole
。
【参考方案1】:
我已经解决了我自己的问题,部分归功于这里的各种建议让我以不同的方式研究它。还注意到 FrontierPsychiatrist 也提供了答案,但我在处理它时没有发现答案。
问题在于 Spring 可互换地指代 ROLES 和 AUTHORITIES。
在实现UserDetailsService
接口以允许Spring 从应用程序数据库加载用户记录后,我正在创建org.springframework.security.core.userdetails.User
的实例并设置授予的权限。可以在日志语句中看到用户对象具有 - Granted Authorities: USER
,但随后我的安全配置正在检查角色,但失败了。简单地说,解决方案是检查权威。我还清理了配置,将要从安全性中忽略的 URL 模式与身份验证和授权分开。完整代码如下sn-p
@Override
public void configure(WebSecurity web) throws Exception
web
.ignoring()
.antMatchers( "/css/**", "/js/**", "/img/**", "/bootstrap/**");
@Override
protected void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
.antMatchers("/individual","/application", "/upload").hasAuthority("USER")
.and()
.formLogin()
.loginPage("/login")
.successHandler(successHandler)
.permitAll()
.and()
.logout()
.deleteCookies("remove")
.logoutSuccessUrl("/login?logout")
.permitAll();
我真的希望这对其他人在使用 Spring 4 MVC 的基于 Java 的配置时有所帮助。
【讨论】:
【参考方案2】:我认为您的登录用户 foo@bar.com 设置了错误的权限。在日志中,您可以看到权限是 ['USER'],但由于您使用的是角色,所以它应该是 ['ROLE_USER']。您在哪里定义 foo@bar.com 的权限?
否则尝试切换
.antMatchers("/individual", "/application", "/upload").hasRole("USER")
到
.antMatchers("/individual", "/application", "/upload").hasAuthority("USER")
【讨论】:
谢谢!在我自己弄清楚之前,我没有看到你的答案。文档对此并不清楚。【参考方案3】:像这样修改你的配置。
http.authorizeRequests().antMatchers("/individual","/application", "/upload")
.hasRole("USER").and().authorizeRequests().anyRequest()
.authenticated().and()
.formLogin()
.loginPage("/login")
.successHandler(successHandler);
如果您不希望对所有请求进行身份验证,您可以将 anyRequest()
方法替换为 antMatchers("/urls-goes-here")
【讨论】:
那行不通。 anyRequest().authenticated() 表示 /login 无法访问,导致重定向循环。删除这意味着所有页面都可以访问 在 antMatchers 中添加 url 模式而不是 anyRequest,然后在其上调用身份验证。我在帖子中提到过。【参考方案4】:这里有一个教程,可以做你想要实现的东西:
http://www.jcombat.com/spring/custom-authentication-success-handler-with-spring-security
我猜你忘了在处理程序中设置会话属性:
HttpSession session = request.getSession();
session.setAttribute("uname", authUser.getUsername());
session.setAttribute("authorities", authentication.getAuthorities());
【讨论】:
Spring 透明地添加“ROLE_”以进行角色匹配。如果您查看示例,只需“USER”即可。 我试过了,但是你得到一个异常原因:java.lang.IllegalArgumentException:角色不应该以'ROLE_'开头,因为它是自动插入的。得到了“ROLE_USER” 好吧,我的错。休息看起来不错,您可以编辑您的原始帖子以包含您的自定义成功处理程序吗? 用教程链接更新了我的答案,请查看并告诉我们它是否有效 这会将检查角色的责任转移给成功处理程序,但仅在登录时。这不会在任何其他时间检查。 url 模式应始终受角色限制。以上是关于具有角色的经过身份验证的用户的 Spring Security Java 配置的主要内容,如果未能解决你的问题,请参考以下文章
AWS - JavaScript - 具有经过身份验证的 Cognito 用户对 DynamoDB 的 CRUD 操作
WSO2IS/APIM:如何在自定义身份验证器中分配用户角色
Spring(引导)具有允许资源的安全预身份验证仍然经过身份验证