栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SAML单点登录-spring-security-saml客户端SP

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SAML单点登录-spring-security-saml客户端SP

SAML单点登录-spring-security-saml客户端SP

使用spring-security-saml搭建SAML协议的客户端,该依赖是spring框架的官方库,配置方便、文档详细。提供了包括单点登录、单点登出、获取sq元数据文件等接口,无需自己实现,参考:spring-security-saml与应用程序的集成

SpringMVC接入 Maven添加spring-security-saml依赖

	org.springframework.security.extensions
	spring-security-saml2-core
	1.0.10.RELEASE

配置文件中添加客户端相关配置
# 认证中心服务信息 -> IDP元数据URL
sp.idpmetadataUrl=http://192.168.59.117:30030/gc-starter-ac/idp/metadata
# entityId,服务提供商唯一标识
sp.entityId=cas:saml:sp:springboot
# 是否签名断言,则需要在idp上传sp的证书/公钥文件以供解密
sp.wantAssertionSigned=false
# 是否签名元数据
sp.signmetadata=false
# 签名算法
sp.signAlg=http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
# 是否启用服务发现。一个sp可以配置多个idp,启动服务发现允许进入idp选择页面选择idp,如果不启用的话默认使用idp列表的第一个
sp.idpDiscoveryEnable=true
# 服务发现选择页面路由
sp.IdpSelectionPath=/saml/discovery
# idp登录成功后的重定向的页面路由,也就是首页路由
sp.successLoginUrl=/landing
# idp登录失败后的重定向的页面路由
sp.failLoginUrl=/error
# 登出成功后跳转的页面路由
sp.successLogoutUrl=/
# jks文件位置
sp.jks.path=classpath:/saml/samlKeystore.jks
# jks密码
sp.jks.password=nalle123
# 默认密钥
sp.jks.defaultKey=apollo

通过xml文件的方式配置bean,classpath下新建securityContext.xml




    
    

    
    

    
    

    
    
        
            
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                    
                    
                    
                        ${sp.idpmetadataUrl}
                    
                    
                    
                        5000
                    
                    
                
                
                
            
        
        
        
        
        
    

    
    
    
        
            
                
                
                
                
                
                    
                
            
        
    

    
    
    
        
    


    
    
    
        
    

    
    
    
        
        
    

    
    
    
        
    

    
    
    
        
        
        
        
        
        
            
                
            
        
        
        
    


    
    
    
     passwords = new HashMap();
        passwords.put(spConfig.getJks().getDefaultKey(), spConfig.getJks().getPassword());
        String defaultKey = spConfig.getJks().getDefaultKey();
        return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
    }
    
    @Bean
    public WebSSOProfileOptions defaultWebSSOProfileOptions() {
        WebSSOProfileOptions webSSOProfileOptions = new WebSSOProfileOptions();
        webSSOProfileOptions.setIncludeScoping(false);
        return webSSOProfileOptions;
    }
 
    // Entry point to initialize authentication, default values taken from
    // properties file
    @Bean
    public SAMLEntryPoint samlEntryPoint() {
        SAMLEntryPoint samlEntryPoint = new SAMLEntryPoint();
        samlEntryPoint.setDefaultProfileOptions(defaultWebSSOProfileOptions());
        return samlEntryPoint;
    }

    // 扩展元数据
    // Setup advanced info about metadata
    @Bean
    public Extendedmetadata extendedmetadata() {
	    Extendedmetadata extendedmetadata = new Extendedmetadata();
	    extendedmetadata.setIdpDiscoveryEnabled(spConfig.getIdpDiscoveryEnable());
	    extendedmetadata.setSigningAlgorithm(spConfig.getSignAlg());
	    extendedmetadata.setSignmetadata(spConfig.getSignmetadata());
	    extendedmetadata.setEcpEnabled(true);
	    return extendedmetadata;
    }

    // 服务发现页面地址
    // IDP Discovery Service
    @Bean
    public SAMLDiscovery samlIDPDiscovery() {
        SAMLDiscovery idpDiscovery = new SAMLDiscovery();
        idpDiscovery.setIdpSelectionPath(spConfig.getIdpSelectionPath());
        return idpDiscovery;
    }
    
	@Bean
	@Qualifier("idp-ssocircle")
	public ExtendedmetadataDelegate ssoCircleExtendedmetadataProvider()
			throws metadataProviderException {
		String idpSSOCirclemetadataURL = spConfig.getIdpmetadataUrl();
		HTTPmetadataProvider httpmetadataProvider = new HTTPmetadataProvider(
				this.backgroundTaskTimer, httpClient(), idpSSOCirclemetadataURL);
		httpmetadataProvider.setParserPool(parserPool());
		ExtendedmetadataDelegate extendedmetadataDelegate = 
				new ExtendedmetadataDelegate(httpmetadataProvider, extendedmetadata());
		extendedmetadataDelegate.setmetadataTrustCheck(false);
		extendedmetadataDelegate.setmetadataRequireSignature(false);
		backgroundTaskTimer.purge();
		return extendedmetadataDelegate;
	}

    // IDP metadata configuration - paths to metadata of IDPs in circle of trust
    // is here
    // Do no forget to call iniitalize method on providers
    @Bean
    @Qualifier("metadata")
    public CachingmetadataManager metadata() throws metadataProviderException {
        List providers = new ArrayList();
        providers.add(ssoCircleExtendedmetadataProvider());
        return new CachingmetadataManager(providers);
    }

    // 元数据生成bean
    // Filter automatically generates default SP metadata
    @Bean
    public metadataGenerator metadataGenerator() {
        metadataGenerator metadataGenerator = new metadataGenerator();
        metadataGenerator.setEntityId(spConfig.getEntityId());
        metadataGenerator.setExtendedmetadata(extendedmetadata());
        metadataGenerator.setIncludeDiscoveryExtension(false);
        metadataGenerator.setKeyManager(keyManager());
        metadataGenerator.setWantAssertionSigned(spConfig.getWantAssertionSigned());
        return metadataGenerator;
    }
 
    // The filter is waiting for connections on URL suffixed with filterSuffix
    // and presents SP metadata there
    @Bean
    public metadataDisplayFilter metadataDisplayFilter() {
        return new metadataDisplayFilter();
    }

    // 设置登陆成功后的重定向地址,或者说是首页地址
    // Handler deciding where to redirect user after successful login
    @Bean
    public SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() {
        SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler =
                new SavedRequestAwareAuthenticationSuccessHandler();
        successRedirectHandler.setDefaultTargetUrl(spConfig.getSuccessLoginUrl());
        return successRedirectHandler;
    }
    
	// Handler deciding where to redirect user after failed login
    @Bean
    public SimpleUrlAuthenticationFailureHandler authenticationFailureHandler() {
	    	SimpleUrlAuthenticationFailureHandler failureHandler =
	    			new SimpleUrlAuthenticationFailureHandler();
	    	failureHandler.setUseForward(true);
	    	failureHandler.setDefaultFailureUrl(spConfig.getFailLoginUrl());
	    	return failureHandler;
    }
     
    @Bean
    public SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter() throws Exception {
        SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter = new SAMLWebSSOHoKProcessingFilter();
        samlWebSSOHoKProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
        samlWebSSOHoKProcessingFilter.setAuthenticationManager(authenticationManager());
        samlWebSSOHoKProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
        return samlWebSSOHoKProcessingFilter;
    }
    
    // Processing filter for WebSSO profile messages
    @Bean
    public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception {
        SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
        samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager());
        samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
        samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
        return samlWebSSOProcessingFilter;
    }
     
    @Bean
    public metadataGeneratorFilter metadataGeneratorFilter() {
        return new metadataGeneratorFilter(metadataGenerator());
    }
     
    // Handler for successful logout
    @Bean
    public SimpleUrlLogoutSuccessHandler successLogoutHandler() {
        SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler();
        successLogoutHandler.setDefaultTargetUrl(spConfig.getSuccessLogoutUrl());
        return successLogoutHandler;
    }
     
    // Logout handler terminating local session
    @Bean
    public SecurityContextLogoutHandler logoutHandler() {
        SecurityContextLogoutHandler logoutHandler = 
        		new SecurityContextLogoutHandler();
        logoutHandler.setInvalidateHttpSession(true);
        logoutHandler.setClearAuthentication(true);
        return logoutHandler;
    }
 
    // Filter processing incoming logout messages
    // First argument determines URL user will be redirected to after successful
    // global logout
    @Bean
    public SAMLLogoutProcessingFilter samlLogoutProcessingFilter() {
        return new SAMLLogoutProcessingFilter(successLogoutHandler(),
                logoutHandler());
    }
     
    // Overrides default logout processing filter with the one processing SAML
    // messages
    @Bean
    public SAMLLogoutFilter samlLogoutFilter() {
        return new SAMLLogoutFilter(successLogoutHandler(),
                new LogoutHandler[] { logoutHandler() },
                new LogoutHandler[] { logoutHandler() });
    }
	
    // Bindings
    private ArtifactResolutionProfile artifactResolutionProfile() {
        final ArtifactResolutionProfileImpl artifactResolutionProfile = 
        		new ArtifactResolutionProfileImpl(httpClient());
        artifactResolutionProfile.setProcessor(new SAMLProcessorImpl(soapBinding()));
        return artifactResolutionProfile;
    }
    
    @Bean
    public HTTPArtifactBinding artifactBinding(ParserPool parserPool, VelocityEngine velocityEngine) {
        return new HTTPArtifactBinding(parserPool, velocityEngine, artifactResolutionProfile());
    }
 
    @Bean
    public HTTPSOAP11Binding soapBinding() {
        return new HTTPSOAP11Binding(parserPool());
    }
    
    @Bean
    public HTTPPostBinding httpPostBinding() {
    		return new HTTPPostBinding(parserPool(), velocityEngine());
    }
    
    @Bean
    public HTTPRedirectDeflateBinding httpRedirectDeflateBinding() {
    		return new HTTPRedirectDeflateBinding(parserPool());
    }
    
    @Bean
    public HTTPSOAP11Binding httpSOAP11Binding() {
    	return new HTTPSOAP11Binding(parserPool());
    }
    
    @Bean
    public HTTPPAOS11Binding httpPAOS11Binding() {
    		return new HTTPPAOS11Binding(parserPool());
    }
    
    // Processor
	@Bean
	public SAMLProcessorImpl processor() {
		Collection bindings = new ArrayList();
		bindings.add(httpRedirectDeflateBinding());
		bindings.add(httpPostBinding());
		bindings.add(artifactBinding(parserPool(), velocityEngine()));
		bindings.add(httpSOAP11Binding());
		bindings.add(httpPAOS11Binding());
		return new SAMLProcessorImpl(bindings);
	}
    
	
    @Bean
    public FilterChainProxy samlFilter() throws Exception {
        List chains = new ArrayList();
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/login
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
     
    
    @Override 
    protected void configure(HttpSecurity http) throws Exception {
        http
            .httpBasic()
                .authenticationEntryPoint(samlEntryPoint());      
        http
        		.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class)
        		.addFilterAfter(samlFilter(), BasicAuthenticationFilter.class)
        		.addFilterBefore(samlFilter(), CsrfFilter.class);
        http        
            .authorizeRequests()
           		.antMatchers("/").permitAll()
           		.antMatchers("/saml
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .authenticationProvider(samlAuthenticationProvider());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        init();
    }

    @Override
    public void destroy() throws Exception {
        shutdown();
    }
}

生成密钥库jks文件

SAML客户端在发送SAML请求时需要进行加密和签名,这就需要密钥,上面配置文件中也有需要去配置jks。jks即密钥库(Java Key Store),里面包含多个公钥和私钥,也可以将认证中心的公钥放入其中,进行解密和验签。这里介绍如何使用jdk的keytool工具生成私钥和自签名证书。

生成密钥库,密钥库包含了公钥和私钥

keytool -genkeypair -alias qianxing -keyalg RSA -keystore samlKeystore.jks

生成公钥,IDP解密时需要使用

keytool -alias qianxing -exportcert -keystore samlKeystore.jks -file public.cer

根据jks生成私钥

keytool -v -importkeystore -srckeystore samlKeystore.jks -srcstoretype jks -destkeystore qianxing.pfx -deststoretype pkcs12
openssl pkcs12 -in qianxing.pfx -nocerts -nodes -out private.key
在idp中注册应用

在之前的文章中的idp工程中classpath下创建一个services目录

新建一个json文件,文件名格式为SAML-XXXXXXXX(唯一标识).json

{
  "@class": "org.apereo.cas.support.saml.services.SamlRegisteredService",
  # sp的entityId
  "serviceId": "com:ustcinfo:qianxing",
  # 服务名称
  "name": "SAMLService",
  # 唯一标识id
  "id": 10000004,
  "evaluationOrder": 10,
  # sp元数据位置
  "metadataLocation": "http://localhost:8100/spring_security_saml2_sample_war/saml/metadata",
  # sp公钥位置,如果不需要加密和签名的话可以先不配置
  "metadataSignatureLocation": "http://localhost:8100/spring_security_saml2_sample_war/key/qianxing.cer",
  # 这是关于加密和签名的配置,暂时先不说,先都设置为false好测试
  "signAssertions": false,
  "signResponses": false,
  "encryptAssertions": false
}

重新部署idp待idp部署成功后,sp客户端打包部署访问sp客户端 sp常用API

获取sp元数据:http://ip:port/cotext-path/saml/metadata

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/733152.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号