代码之家  ›  专栏  ›  技术社区  ›  Jim

azure广告B2C,java应用程序

  •  1
  • Jim  · 技术社区  · 7 年前

    我搜索了很多关于Azure AD B2C安全性对Spring boot、REST实现的支持,但除了Azure AD应用程序或.net应用程序之外,什么都找不到。

    这是否意味着Azure AD B2C不支持java/spring启动应用程序?

    如果可能,是否有人尝试过,并让我知道需要从Azure AD web应用更改为Azure AD B2C web应用。

    期待您的支持。

    谢谢

    1 回复  |  直到 7 年前
        1
  •  1
  •   Karol Leszczyński    7 年前

    是的:)

    用于Spring授权服务器和资源服务器。我最近的实现是Resource Server(如果你只需要保护REST API,你的应用程序只使用令牌,其他前端应用程序负责登录重定向等,那么这是最好的),这是一个关于使用oAuth2的spring安全性的很好教程,你可以在 baeldung . 我基于教程的安全配置是:

        @Configuration
        @EnableResourceServer
        @EnableScheduling
        @RequiredArgsConstructor   
        public class SecurityResourceServerConfig extends ResourceServerConfigurerAdapter {
    
        @Value("${b2c.client-id}")
        private String resourceId;
    
        private final KeyUtilHandler keyUtilHandler;
    
        @Primary
        @Bean
        public DefaultTokenServices customTokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
            defaultTokenServices.setTokenStore(tokenStore());
            return defaultTokenServices;
        }
    
        @Bean
        public TokenStore tokenStore() {
            return new JwtTokenStore(accessTokenConverter());
        }
    
        @Bean
        public JwtAccessTokenConverter accessTokenConverter() {
    
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setVerifierKey(keyUtilHandler.stringPublicKey());
    
            return converter;
        }
    
        @Override
        public void configure(ResourceServerSecurityConfigurer configurer) {
            configurer.resourceId(resourceId);
            configurer.tokenServices(customTokenServices());
        }
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
    
            http
                    .sessionManagement().sessionCreationPolicy(STATELESS)
                    .and()
                    .authorizeRequests()
                    .anyRequest()
                    .authenticated();
    
        }
    }
    

    如果您在token converter中提供资源id(azure客户端id)和验证器密钥(setVerifierKey),Spring将负责向链中添加一个过滤器,以验证来自token的签名和基本声明。这就是安全配置。另一件事是azure不提供令牌中的密钥,您可以通过密钥id(“kid”in token)找到合适的公钥。Azure还提供nessecary值来编码密钥,它们可以在为每个b2c租户创建的端点的json对象中找到-

    https://login.microsoftonline.com/ {您的租户名称}/discovery/v2。0/键?p={您的登录注册策略}

    例如:https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/discovery/v2.0/keys?p=b2c_1_sign_in

    {
      "keys": [
        {"kid":"X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk","nbf":1493763266,"use":"sig","kty":"RSA","e":"AQAB","n":"tVKUtcx_n9rt5afY_2WFNvU6PlFMggCatsZ3l4RjKxH0jgdLq6CScb0P3ZGXYbPzXvmmLiWZizpb-h0qup5jznOvOr-Dhw9908584BSgC83YacjWNqEK3urxhyE2jWjwRm2N95WGgb5mzE5XmZIvkvyXnn7X8dvgFPF5QwIngGsDG8LyHuJWlaDhr_EPLMW4wHvH0zZCuRMARIJmmqiMy3VD4ftq4nS5s8vJL0pVSrkuNojtokp84AtkADCDU_BUhrc2sIgfnvZ03koCQRoZmWiHu86SuJZYkDFstVTVSR0hiXudFlfQ2rOhPlpObmku68lXw-7V-P7jwrQRFfQVXw"}
      ]
    }
    

    您需要“n”和“e”值来为客户端应用程序编码有效密钥。有现成的库,但您可以编写自己的实现。我还使用rest模板获取json并提取值。根据microsoft文档,密钥可以随时更改,所以您可能需要安排方法。

    public class KeyUtilHandler {
    
        @Value("${b2c.key-url}")
        private String keyUrl;
    
        @Value("${b2c.sign-up-or-in-user-flow}")
        private String signUpOrInUserFlow;
    
        @Value("${b2c.tenant}")
        private String tenant;
    
        private String eValue;
        private String nValue;
    
        public String stringPublicKey(){
    
            setAzureKeys();
    
            byte[] modulusBytes = Base64.getUrlDecoder().decode(nValue);
            BigInteger modulusInt = new BigInteger(1, modulusBytes);
    
            byte[] exponentBytes = Base64.getUrlDecoder().decode(eValue);
            BigInteger exponentInt = new BigInteger(1, exponentBytes);
    
            KeyFactory keyFactory;
    
            RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(modulusInt, exponentInt);
    
            String encodedStringKey = null;
    
            {
                try {
                    keyFactory = KeyFactory.getInstance("RSA");
    
                    RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(publicSpec);
    
                    byte [] encodedKey = publicKey.getEncoded();
    
                    encodedStringKey = Base64.getEncoder().encodeToString(encodedKey);
    
                } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
                    e.printStackTrace();
                }
            }
    
            return String.format("-----BEGIN PUBLIC KEY-----%s-----END PUBLIC KEY-----"
                        , encodedStringKey);
    
        }
    
        private void setAzureKeys (){
    
            String resolvedKeyUrl = String.format(keyUrl, tenant, signUpOrInUserFlow);
    
            RestTemplate azureKeys = new RestTemplate();
            AzureKeySetDto result = azureKeys.getForObject(resolvedKeyUrl, AzureKeySetDto.class);
            if (Objects.isNull(result.getKeys())) {
                throw new UnableToGetResourceException();
            }
            Map<String, String> keyMap = result.getKeys().stream()
                    .findFirst()
                    .get();
            eValue = keyMap.get("e");
            nValue = keyMap.get("n");
        }
    
        @Scheduled(fixedRate = TWENTY_HOURS_IN_MILIS)
        private void renewKeys(){
                setAzureKeys();
        }
    }
    
        2
  •  0
  •   Hannahwy    7 年前

    这 tutorial 演示如何使用Azure AD B2C(Azure Active Directory)保护Spring Boot web服务后端。您可以在GitHub存储库中找到完整的代码。看看这个文件,希望它会有帮助!