Spring Security SAML:让 块出现在

2024-05-27

我很难让 Spring Security SAML 与 ADFS 2.0 一起使用。

根据我当前的配置,生成的AuthnRequest看起来像这样:-

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest
    AssertionConsumerServiceURL="https://localhost:8443/helix/saml/SSO"
    Destination="https://server/adfs/ls/"
    ForceAuthn="false" ID="a14edaf38ih92bi8acji5a1664a80e"
    IsPassive="false" IssueInstant="2016-02-15T21:05:57.980Z"
    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
    Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://localhost:8443/helix/saml/metadata</saml2:Issuer>
    <saml2p:Scoping ProxyCount="2"/>
</saml2p:AuthnRequest>

但是,它会在 ADFS 端导致错误:-

Microsoft.IdentityModel.Protocols.XmlSignature.SignatureVerificationFailedException: MSIS0038: SAML Message has wrong signature. Issuer: 'https://localhost:8443/helix/saml/metadata'.
   at Microsoft.IdentityServer.Protocols.Saml.Contract.SamlContractUtility.CreateSamlMessage(MSISSamlBindingMessage message)
   at Microsoft.IdentityServer.Service.SamlProtocol.SamlProtocolService.CreateErrorMessage(CreateErrorMessageRequest createErrorMessageRequest)
   at Microsoft.IdentityServer.Service.SamlProtocol.SamlProtocolService.ProcessRequest(Message requestMessage)

我的安全团队告诉我,我的AuthnRequest应该看起来像这样:-

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://localhost:8443/helix/saml/SSO" Destination="https://server/adfs/ls/" ID="_e082771303738e4e6872e8d5711446d4" IssueInstant="2016-02-15T19:51:50.627Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://localhost:8443/helix/saml/metadata</saml2:Issuer>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
            <Reference URI="#_e082771303738e4e6872e8d5711446d4">
                <Transforms>
                    <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                    <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <DigestValue>S8r/XbIhlFGFSMfLoSt/7IlksiI=</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>TT4n3==...</SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>MIIC8z...</X509Certificate>
            </X509Data>
        </KeyInfo>
    </Signature>
    <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
    <saml2p:RequestedAuthnContext Comparison="exact">
        <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
    </saml2p:RequestedAuthnContext>
</saml2p:AuthnRequest>

...但是,我在尝试制作时遇到了麻烦<Signature>阻止出现在我的AuthnRequest.

我当前的 Spring Security SAML 配置如下所示...我很抱歉它相当冗长,但我不确定除了整个配置之外还要粘贴什么。

@Configuration
@EnableWebSecurity
public abstract class SecuritySAMLConfig extends WebSecurityConfigurerAdapter {
    private static final String METADATA_URL = "https://server/federationmetadata/2007-06/federationmetadata.xml";
    private static final String ALIAS = "apollo";
    private static final String STORE_PASS = "secret";

    @Autowired
    private SAMLUserDetailsServiceImpl samlUserDetailsServiceImpl;

    @Autowired
    private SAMLAuthenticationProvider samlAuthenticationProvider;

    @Bean
    public static SAMLBootstrap SAMLBootstrap() {
        return new CustomSamlBootstrap();
    }

    @Bean
    public VelocityEngine velocityEngine() {
        return VelocityFactory.getEngine();
    }

    @Bean(initMethod = "initialize")
    public StaticBasicParserPool parserPool() {
        return new StaticBasicParserPool();
    }

    @Bean(name = "parserPoolHolder")
    public ParserPoolHolder parserPoolHolder() {
        return new ParserPoolHolder();
    }

    @Bean
    public MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager() {
        return new MultiThreadedHttpConnectionManager();
    }

    @Bean
    public HttpClient httpClient(MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager) {
        return new HttpClient(multiThreadedHttpConnectionManager);
    }

    @Bean
    public SAMLAuthenticationProvider samlAuthenticationProvider() {
        SAMLAuthenticationProvider samlAuthenticationProvider = new SAMLAuthenticationProvider();
        samlAuthenticationProvider.setUserDetails(samlUserDetailsServiceImpl);
        samlAuthenticationProvider.setForcePrincipalAsString(false);
        return samlAuthenticationProvider;
    }

    @Bean
    public SAMLContextProviderImpl contextProvider() {
        return new SAMLContextProviderImpl();
    }

    @Bean
    public SAMLDefaultLogger samlLogger() {
        return new SAMLDefaultLogger();
    }

    @Bean
    public WebSSOProfileConsumer webSSOprofileConsumer() {
        return new WebSSOProfileConsumerImpl();
    }

    @Bean
    public WebSSOProfileConsumerHoKImpl hokWebSSOprofileConsumer() {
        return new WebSSOProfileConsumerHoKImpl();
    }

    @Bean
    public WebSSOProfile webSSOprofile() {
        return new WebSSOProfileImpl();
    }

    @Bean
    public WebSSOProfileConsumerHoKImpl hokWebSSOProfile() {
        return new WebSSOProfileConsumerHoKImpl();
    }

    @Bean
    public WebSSOProfileECPImpl ecpprofile() {
        return new WebSSOProfileECPImpl();
    }

    @Bean
    public SingleLogoutProfile logoutprofile() {
        return new SingleLogoutProfileImpl();
    }

    @Bean
    public KeyManager keyManager() {
        DefaultResourceLoader loader = new DefaultResourceLoader();
        Resource storeFile = loader.getResource("classpath:keystore.jks");
        Map<String, String> passwords = new HashMap<>();
        passwords.put(ALIAS, STORE_PASS);
        return new JKSKeyManager(storeFile, STORE_PASS, passwords, ALIAS);
    }

    @Bean
    public WebSSOProfileOptions webSSOProfileOptions() {
        return new WebSSOProfileOptions();
    }

    @Bean
    public SAMLEntryPoint samlEntryPoint(WebSSOProfileOptions webSSOProfileOptions) {
        SAMLEntryPoint samlEntryPoint = new SAMLEntryPoint();
        samlEntryPoint.setDefaultProfileOptions(webSSOProfileOptions);
        return samlEntryPoint;
    }

    @Bean
    public ExtendedMetadata extendedMetadata() {
        ExtendedMetadata extendedMetadata = new ExtendedMetadata();
        extendedMetadata.setIdpDiscoveryEnabled(false);

        // #######
        // ####### In theory, by setting these keys, the signature block should appear,
        // ####### but, that didn't work for me
        // #######
        extendedMetadata.setSignMetadata(true);
        extendedMetadata.setSigningKey(ALIAS);
        extendedMetadata.setEncryptionKey(ALIAS);
        // #######

        return extendedMetadata;
    }

    @Bean
    public ExtendedMetadataDelegate extendedMetadataDelegate(HttpClient httpClient,
                                                             ParserPool parserPool,
                                                             ExtendedMetadata extendedMetadata) throws MetadataProviderException {
        Timer backgroundTaskTimer = new Timer(true);
        HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider(backgroundTaskTimer,
                                                                             httpClient,
                                                                             METADATA_URL);
        httpMetadataProvider.setParserPool(parserPool);
        ExtendedMetadataDelegate extendedMetadataDelegate = new ExtendedMetadataDelegate(httpMetadataProvider,
                                                                                         extendedMetadata);
        extendedMetadataDelegate.setMetadataTrustCheck(false);

        return extendedMetadataDelegate;
    }

    @Bean
    public CachingMetadataManager metadata(ExtendedMetadataDelegate extendedMetadataDelegate) throws MetadataProviderException {
        List<MetadataProvider> providers = new ArrayList<>();
        providers.add(extendedMetadataDelegate);
        return new CachingMetadataManager(providers);
    }

    @Bean
    public MetadataGenerator metadataGenerator(ExtendedMetadata extendedMetadata, KeyManager keyManager) {
        MetadataGenerator metadataGenerator = new MetadataGenerator();

        metadataGenerator.setExtendedMetadata(extendedMetadata);
        metadataGenerator.setIncludeDiscoveryExtension(false);
        metadataGenerator.setKeyManager(keyManager);

        return metadataGenerator;
    }

    @Bean
    public MetadataDisplayFilter metadataDisplayFilter() {
        return new MetadataDisplayFilter();
    }

    @Bean
    public SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler() {
        SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successRedirectHandler.setDefaultTargetUrl("/landing");
        return successRedirectHandler;
    }

    @Bean
    public SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler() {
        SimpleUrlAuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
        failureHandler.setUseForward(true);
        failureHandler.setDefaultFailureUrl("/error");
        return failureHandler;
    }

    @Bean
    public SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter(SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler,
                                                                       AuthenticationManager authenticationManager,
                                                                       SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler) throws Exception {
        SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter = new SAMLWebSSOHoKProcessingFilter();
        samlWebSSOHoKProcessingFilter.setAuthenticationSuccessHandler(savedRequestAwareAuthenticationSuccessHandler);
        samlWebSSOHoKProcessingFilter.setAuthenticationManager(authenticationManager);
        samlWebSSOHoKProcessingFilter.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler);
        return samlWebSSOHoKProcessingFilter;
    }

    @Bean
    public SAMLProcessingFilter samlProcessingFilter(AuthenticationManager authenticationManager,
                                                     SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler,
                                                     SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler) throws Exception {
        SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
        samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager);
        samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(savedRequestAwareAuthenticationSuccessHandler);
        samlWebSSOProcessingFilter.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler);
        return samlWebSSOProcessingFilter;
    }

    @Bean
    public MetadataGeneratorFilter metadataGeneratorFilter(MetadataGenerator metadataGenerator) {
        return new MetadataGeneratorFilter(metadataGenerator);
    }

    @Bean
    public SimpleUrlLogoutSuccessHandler simpleUrlLogoutSuccessHandler() {
        SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler();
        successLogoutHandler.setDefaultTargetUrl("/");
        return successLogoutHandler;
    }

    @Bean
    public SecurityContextLogoutHandler securityContextLogoutHandler() {
        SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
        logoutHandler.setInvalidateHttpSession(true);
        logoutHandler.setClearAuthentication(true);
        return logoutHandler;
    }

    @Bean
    public SAMLLogoutProcessingFilter samlLogoutProcessingFilter(SimpleUrlLogoutSuccessHandler simpleUrlLogoutSuccessHandler,
                                                                 SecurityContextLogoutHandler securityContextLogoutHandler) {
        return new SAMLLogoutProcessingFilter(simpleUrlLogoutSuccessHandler, securityContextLogoutHandler);
    }

    @Bean
    public SAMLLogoutFilter samlLogoutFilter(SimpleUrlLogoutSuccessHandler simpleUrlLogoutSuccessHandler,
                                             SecurityContextLogoutHandler securityContextLogoutHandler) {
        return new SAMLLogoutFilter(simpleUrlLogoutSuccessHandler,
                                    new LogoutHandler[]{securityContextLogoutHandler},
                                    new LogoutHandler[]{securityContextLogoutHandler});
    }

    @Bean
    public HTTPArtifactBinding artifactBinding(HTTPSOAP11Binding httpSOAP11Binding,
                                               HttpClient httpClient,
                                               ParserPool parserPool,
                                               VelocityEngine velocityEngine) {
        ArtifactResolutionProfileImpl artifactResolutionProfile = new ArtifactResolutionProfileImpl(httpClient);
        artifactResolutionProfile.setProcessor(new SAMLProcessorImpl(httpSOAP11Binding));

        return new HTTPArtifactBinding(parserPool, velocityEngine, artifactResolutionProfile);
    }

    @Bean
    public HTTPSOAP11Binding httpSOAP11Binding(ParserPool parserPool) {
        return new HTTPSOAP11Binding(parserPool);
    }

    @Bean
    public HTTPPostBinding httpPostBinding(ParserPool parserPool, VelocityEngine velocityEngine) {
        return new HTTPPostBinding(parserPool, velocityEngine);
    }

    @Bean
    public HTTPRedirectDeflateBinding httpRedirectDeflateBinding(ParserPool parserPool) {
        return new HTTPRedirectDeflateBinding(parserPool);
    }

    @Bean
    public HTTPPAOS11Binding httpPAOS11Binding(ParserPool parserPool) {
        return new HTTPPAOS11Binding(parserPool);
    }

    @Bean
    public SAMLProcessorImpl processor(HTTPRedirectDeflateBinding httpRedirectDeflateBinding,
                                       HTTPPostBinding httpPostBinding,
                                       HTTPArtifactBinding httpArtifactBinding,
                                       HTTPSOAP11Binding httpSOAP11Binding,
                                       HTTPPAOS11Binding httpPAOS11Binding) {
        Collection<SAMLBinding> bindings = new ArrayList<>();
        bindings.add(httpRedirectDeflateBinding);
        bindings.add(httpPostBinding);
        bindings.add(httpArtifactBinding);
        bindings.add(httpSOAP11Binding);
        bindings.add(httpPAOS11Binding);
        return new SAMLProcessorImpl(bindings);
    }

    @Bean
    public FilterChainProxy filterChainProxy(SAMLEntryPoint samlEntryPoint,
                                             SAMLLogoutFilter samlLogoutFilter,
                                             MetadataDisplayFilter metadataDisplayFilter,
                                             SAMLProcessingFilter samlProcessingFilter,
                                             SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter,
                                             SAMLLogoutProcessingFilter samlLogoutProcessingFilter) throws Exception {
        List<SecurityFilterChain> chains = new ArrayList<>();
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/login/**"), samlEntryPoint));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/logout/**"), samlLogoutFilter));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/metadata/**"),
                                                  metadataDisplayFilter));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSO/**"), samlProcessingFilter));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSOHoK/**"),
                                                  samlWebSSOHoKProcessingFilter));
        chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SingleLogout/**"),
                                                  samlLogoutProcessingFilter));

        return new FilterChainProxy(chains);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(samlAuthenticationProvider);
    }
}

如果有人能将我推向正确的方向,我将非常感激。

谢谢。

UPDATE

我的 SP 元数据生成者MetadataGenerator看起来像这样:-

<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="https___localhost_8443_helix_saml_metadata" entityID="https://localhost:8443/helix/saml/metadata">
    <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
        <md:KeyDescriptor use="signing">
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <ds:X509Data>
                    <ds:X509Certificate>MIICx....</ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </md:KeyDescriptor>
        <md:KeyDescriptor use="encryption">
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <ds:X509Data>
                    <ds:X509Certificate>MIICxz....</ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </md:KeyDescriptor>
        <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://localhost:8443/helix/saml/SingleLogout"/>
        <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://localhost:8443/helix/saml/SingleLogout"/>
        <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
        <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
        <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
        <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
        <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</md:NameIDFormat>
        <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://localhost:8443/helix/saml/SSO" index="0" isDefault="true"/>
        <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://localhost:8443/helix/saml/SSO" index="1"/>
    </md:SPSSODescriptor>
</md:EntityDescriptor>

我还想指出,我使用的是 SHA256withRSA 而不是 SHA1withRSA。因此,我替换了默认的SAMLBootstrap豆与以下:-

public final class CustomSamlBootstrap extends SAMLBootstrap {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        super.postProcessBeanFactory(beanFactory);
        BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration();
        config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
        config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
    }
}

UPDATE 2

我通过修改让它工作WebSSOProfileOptions.

@Bean
public WebSSOProfileOptions webSSOProfileOptions() {
    WebSSOProfileOptions webSSOProfileOptions = new WebSSOProfileOptions();
    webSSOProfileOptions.setIncludeScoping(false);

    // Added this line
    webSSOProfileOptions.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);

    return webSSOProfileOptions;
}

您使用什么绑定将请求发送到 IDP?如果是 HTTP 请求,SAML 标准要求在传递消息之前删除签名。然后对序列化请求执行签名并作为 GET 参数发送。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Security SAML:让 块出现在 中 的相关文章

随机推荐

  • MySQL - 重命名列

    如何重命名 mysql 列help to content在我的桌子上tbl help mysql query ALTER TABLE tbl help CHANGE COLUMN help content 您必须在更改列语句中包含列的定义
  • 关闭后如果日志文件为空,则删除日志文件

    我有一个库函数 可以启动通用后台进程并记录它 def LaunchAndLog cmd cmd args cmd split Split arguments into array logfile cmd args 0 log with op
  • 在 Windows Phone 8 中以编程方式下载媒体文件

    我们的应用程序是基于视频 音频的应用程序 我们已将所有媒体上传到 Windows Azure 上 但需要方便用户点播下载音视频文件 以便在本地播放 所以我需要以编程方式下载音频 视频文件并将其保存在IsolatedStorage中 我们有每
  • 在 Play Services 8.3 中的新 Google 登录中获取人员详细信息

    我正在尝试使用 Play Services 8 3 中引入的新 Google Sign In API 获取用户的个人资料 除了显示名称 电子邮件和 ID 之外 我还需要用户的性别 Plus PeopleApi getCurrentPerso
  • 关于 C++ 中的 STL 容器的问题

    std multimap 和 std unordered multimap 多久洗一次条目 我这么问是因为我的代码传递引用来区分具有相同哈希的条目 并且我想知道何时对它们运行引用重定向功能 如果我这样做会发生什么 std multimap
  • R Markdown / Bookdown 中的水平规则导致错误

    突然 我在 Markdown Bookdown 中编织为 PDF 时遇到错误 我的系统没有任何变化 该错误是由 水平规则 引起的 即 Markdown 中的任意位置 或 尽管两侧都有行空格 我提供了一个简单的违规示例 它不会合并成 PDF
  • WinForm面板滚动没有滚动条?

    我正在创建一个基本上是一个面板的用户控件 内部有随机内容 并且我需要能够使用按钮 向上和向下 而不是滚动条来上下滚动该面板 我必须这样做的原因是因为该程序将在触摸屏显示器上使用 我们需要大按钮而不是丑陋的小滚动条 我一直在摆弄 Vertic
  • Scala - lambda 参数可以匹配元组吗?

    所以说我有一些清单 比如 val l List 1 blue 5 red 2 green 然后我想过滤掉其中一个 我可以做类似的事情 val m l filter item gt val n s item unpack the tuple
  • 提高 Pandas 合并性能

    正如其他帖子所建议的那样 我特别没有 Pandas Merge 的性能问题 但我有一个类 其中有很多方法 可以对数据集进行大量合并 该类有大约 10 个 group by 和大约 15 个 merge 虽然 groupby 相当快 但在类的
  • C语言中的“宽字符串”是什么?

    我在书中看到这样一句话 wscanf L lf variable 其中第一个参数的类型为wchar t 这不同于scanf lf variable 其中第一个参数的类型为char 那么比起来有什么区别呢 我以前从未听说过 宽字符串 我听说过
  • 为什么我们(必须)使用不同的启动器图标(xhdpi、hdpi 等)

    我想知道 为什么我们在 android 中使用不同的启动器图标 大小 目前您 必须 将图标大小调整为 LDPI 36 x 36 MDPI 48 x 48 HDPI 72 x 72 XHDPI 96 x 96 并将它们放入所需的文件夹中 但是
  • 如何在 PySimpleGUIQt 中实现复选框功能?

    我正在尝试用 Python 创建一个简单的 GUI 程序 我将在创建新项目时使用它 我想要一个用于项目类型 python web 等 的复选框功能 然后是项目名称的输入框 目录名称是什么 import os import PySimpleG
  • Python - 在大型数据集上计算多项概率密度函数?

    我原本打算使用 MATLAB 来解决这个问题 但内置函数有局限性 不适合我的目标 NumPy 中也存在同样的限制 我有两个制表符分隔的文件 第一个是显示内部蛋白质结构数据库的氨基酸残基 频率和计数的文件 即 A 0 25 1 S 0 25
  • iOS 联系人 如何通过电话号码获取联系人

    我只想通过电话号码获取联系人姓名 我尝试过这个 但速度太慢 CPU 速度超过 120 let contactStore CNContactStore let keys CNContactGivenNameKey CNContactFamil
  • 在 matplotlib 中用圆裁剪三角形

    我想画一个三角形 但其中一条边需要是圆弧段 该示例不起作用 需要删除圆圈外的所有蓝色 可以直接完成此操作 而无需自己计算整个轮廓吗 谢谢你 import matplotlib pyplot as plt fig plt figure ax
  • 在 Ubuntu 上安装软件包需要很长时间

    我之前使用 Windows 作为操作系统 RStudio 用于 Windows 今天切换到 Ubuntu 并再次安装了 R 和 RStudio 当我尝试从 CRAN 安装一些软件包时 仅tidyverse 使用install package
  • 按索引偶数或奇数将数组拆分为两个数组

    我有这个数组 array array a b c d e f g 我想根据索引是偶数还是奇数将其分成两个数组 如下所示 odd array a c e g even array b d f 提前致谢 一种解决方案 使用匿名函数和array
  • 在 JSP 中从 JavaScript/jQuery 调用后端 Java 方法

    我有一个 JSP 其中有一个select包含实体种类名称的列表 当我选择一个实体类型时 我需要填充另一个实体类型select包含所选实体类型的字段名称的列表 为此 我调用了一个 JavaScript 函数onchange event 在 J
  • ios 无法将图片上传到服务器

    您好 我正在尝试将图像从我的 IOS 设备上传到服务器 这是我上传图像的代码 IBAction btnUpload id sender if self imageViewGallery image nil UIAlertView Error
  • Spring Security SAML:让 块出现在

    我很难让 Spring Security SAML 与 ADFS 2 0 一起使用 根据我当前的配置 生成的AuthnRequest看起来像这样