如何在 SAML 中创建内存用户 [英] How to create an in memory user in SAML
问题描述
我在以下链接的帮助下使用 spring boot 1.4.0+spring-security-saml2-core 1.0.2 Spring-Boot-Saml-example 它运行良好.现在我想创建一个与 SAML 用户具有相同授予权限的内存用户.请找到以下 SAMLUserDetailsServiceImpl 代码以供参考.您的帮助应该是可观的.
Hi I am using spring boot 1.4.0+spring-security-saml2-core 1.0.2 with the help of following link Spring-Boot-Saml-example it is working great. Now i would like to create an in memory user with the same granted authorities that the SAML user is issued.Kindly find the below code of SAMLUserDetailsServiceImpl for reference.Your help should be appreciable.
@Service
public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService {
// Logger
private static final Logger LOG = LoggerFactory.getLogger(SAMLUserDetailsServiceImpl.class);
@Value("${emailSamlAttrName}")
private String emailSamlAttrName;
public Object loadUserBySAML(SAMLCredential credential)
throws UsernameNotFoundException {
// The method is supposed to identify local account of user referenced by
// data in the SAML assertion and return UserDetails object describing the user.
String userID = credential.getNameID().getValue();
Attribute emailAttribute = credential.getAttribute(emailSamlAttrName);
String userEmail = getAttributeValue(credential.getAttribute(emailSamlAttrName).getAttributeValues().get(0));
LOG.info(userID + " is logged in");
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
authorities.add(authority);
// In a real scenario, this implementation has to locate user in a arbitrary
// dataStore based on information present in the SAMLCredential and
// returns such a date in a form of application specific UserDetails object.
return new User(userID, "<abc123>", true, true, true, true, authorities);
}
根据@blur0224 评论,我将以下代码放入:
As per the @blur0224 comment i put the following code in:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("sample").password("sample123").roles("NONE");
auth.inMemoryAuthentication().withUser("dummy").password("dummy123").roles("USER");
auth.inMemoryAuthentication().withUser("proxy").password("proxy123").roles("USER");
}
但它抛出以下错误....
But it throws the following error....
11:09:41.345 [http-nio-8040-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor [transactionId: ]- Secure object: FilterInvocation: URL: /api/v1/users/authenticated; Attributes: [hasRole('ROLE_NONE') or hasRole('ROLE_USER')]
11:09:41.345 [http-nio-8040-exec-1] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor [transactionId: ]- Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2b c: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
11:09:41.351 [http-nio-8040-exec-1] DEBUG o.s.s.access.vote.AffirmativeBased [transactionId: ]- Voter: org.springframework.security.web.access.expression.WebExpressionVoter@2809e0b9, returned: -1
11:09:41.352 [http-nio-8040-exec-1] DEBUG o.s.b.f.s.DefaultListableBeanFactory [transactionId: ]- Returning cached instance of singleton bean 'delegatingApplicationListener'
11:09:41.352 [http-nio-8040-exec-1] DEBUG o.s.b.f.s.DefaultListableBeanFactory [transactionId: ]- Returning cached instance of singleton bean 'authorizationAuditListener'
11:09:41.354 [http-nio-8040-exec-1] DEBUG o.s.b.f.s.DefaultListableBeanFactory [transactionId: ]- Returning cached instance of singleton bean 'delegatingApplicationListener'
11:09:41.354 [http-nio-8040-exec-1] DEBUG o.s.b.f.s.DefaultListableBeanFactory [transactionId: ]- Returning cached instance of singleton bean 'auditListener'
11:09:41.354 [http-nio-8040-exec-1] DEBUG o.s.b.a.audit.listener.AuditListener [transactionId: ]- AuditEvent [timestamp=Wed Jul 27 11:09:41 CEST 2016, principal=anonymousUser, type=AUTHORIZATION_FAILURE, data={type=org.springframework.security.access.AccessDeniedException, message=Access is denied}]
11:09:41.359 [http-nio-8040-exec-1] DEBUG o.s.s.w.a.ExceptionTranslationFilter [transactionId: ]- Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:232)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:123)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:207)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.saml.metadata.MetadataGeneratorFilter.doFilter(MetadataGeneratorFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:103)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:676)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
WebSecurityConfig.java
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.authenticationEntryPoint(samlEntryPoint());
http
.csrf()
.disable();
http
.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
.addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/error").permitAll()
.antMatchers("/saml/**").permitAll()
.antMatchers("/api/*/users/authenticated").access(String.format("hasRole('%s') or hasRole('%s')", ROLE_NONE, ROLE_USER))
.antMatchers("/api/**").access(String.format("hasRole('%s')", ROLE_USER))
.anyRequest().access(String.format("hasRole('%s')", ROLE_USER));
http
.logout()
.logoutSuccessUrl("/");
}
推荐答案
在您的 SAMLUserDetailsServiceImpl
中,您当前没有在数据库中查找用户以获取有关他们的任何特定信息.在这种情况下,您可以设置本地安全配置,以在内存中创建用户,其授予的权限与他们通过 SAML 时拥有的权限相同.ROLE_USER
您可以使用下面的示例作为指南来设置您可以像本地开发一样登录的用户.
In your SAMLUserDetailsServiceImpl
you are currently not looking up the user in a DB to get any specific information about them. This being the case, you can setup your local security configuration to create in memory users with the same granted authority they have when they go through SAML. ROLE_USER
You can use the example below as a guide for setting up a user that you can log in as for your local development.
你错过了吗?
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/info/**").hasAnyRole("ADMIN","USER").
and().formLogin();
}
您需要两个单独的安全配置:WebSecurityConfig
和 LocalSecurityConfig
在本地运行时,您需要最快速、最简单的方法来复制您的 saml 实现为您提供的内容,即具有授予权限的用户.请注意,您的 SAML 配置文件需要 @Profile("dev","test","prod")
WebSecurityConfig
You need two separate security configurations: WebSecurityConfig
and LocalSecurityConfig
When running locally you want the quickest, easiest way to replicate what your implementation of saml provides you with, which is a user with granted authorities. Note that you will need to have @Profile("dev","test","prod")
on your SAML Configuration files WebSecurityConfig
@Configuration
@ComponentScan("com.whatever.etc")
@EnableWebSecurity
@Profile("local")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasAnyRole("ADMIN","USER").
and().httpBasic();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("ram").password("ram123").roles("ADMIN");
auth.inMemoryAuthentication().withUser("ravan").password("ravan123").roles("USER");
auth.inMemoryAuthentication().withUser("kans").password("kans123").roles("USER");
}
}
您不能简单地将用户添加到 SAML 配置中,因为它具有不同的入口点.通过创建单独的配置,您可以精细控制您希望应用程序如何仅在本地运行.此外,可以但没有必要将两个配置合并到一个文件中.我建议先让他们分开工作.
You can't simply add users to the SAML configuration because the it has a different entry point. By creating a separate configuration, you have granular control of how you want the application to behave running locally only. Also, it is possible but not necessary to combine the two configurations into a single file. I would recommend getting them working separately first.
这篇关于如何在 SAML 中创建内存用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!