当前位置: 首页 > 知识库问答 >
问题:

在Spring Boot中尝试实现Azure AD身份验证和授权时出现异常

呼延曜灿
2023-03-14

我收到以下错误:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChainProxySecurityConfigurer' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2WebSecurityConfiguration$OAuth2WebSecurityConfigurerAdapter': Unsatisfied dependency expressed through method 'setContentNegotationStrategy' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setClientRegistrationRepository' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientRegistrationRepositoryConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'spring.security.oauth2.client-org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Client id must not be empty.

尽管我在应用程序中提供了客户机ID。属性

我点击了以下链接:https://docs.microsoft.com/en-us/azure/developer/java/spring-framework/configure-spring-boot-starter-java-app-with-azure-active-directory

POM:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
    <relativePath />
    <!-- lookup parent from repository -->
</parent>
<groupId>com.mmm</groupId>
<artifactId>UserMgmt</artifactId>
<version>1.0.3</version>
<packaging>war</packaging>
<name>UserMgmt</name>
<description>User Management</description>
<!-- FIXME change it to the project's website -->
<!-- <url>http://www.example.com</url> -->
<properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
    </dependency>
        <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-dynamodb</artifactId>
        <version>1.11.956</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-lambda</artifactId>
        <version>1.11.207</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.janino</groupId>
        <artifactId>janino</artifactId>
        <version>2.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.13</version>
    </dependency>
    <dependency>     
        <groupId>com.google.code.gson</groupId>     
        <artifactId>gson</artifactId>     
        <version>2.8.6</version>     
        </dependency>   
        <dependency>
        <groupId>com.sun.mail</groupId>
        <artifactId>javax.mail</artifactId>
        <version>1.6.2</version>
    </dependency>
    
    <dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-active-directory-spring-boot-starter</artifactId>
    <version>2.1.6</version>
    </dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>


</dependencies>
<build> 
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
        
    
    <pluginManagement>

        <plugins>
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.1.0</version>
            </plugin>
                <plugin>
                <groupId>org.jboss.as.plugins</groupId>
                <artifactId>jboss-as-maven-plugin</artifactId>
                <version>7.9.Final</version>
                </plugin>
            
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.0.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.6</version>
            </plugin>
            <plugin>
                <artifactId>maven-install-plugin</artifactId>
                <version>2.5.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8.2</version>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
</project>

主要内容:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@SpringBootApplication
public class UserApplication extends SpringBootServletInitializer {
private static final Logger LOG = 
LoggerFactory.getLogger(UserApplication.class.getName());


public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);

}

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder 
application) {
return application.sources(UserApplication.class);
}

@Configuration
public class DataSourceConfiguration {/*creds*/}

控制器

@RequestMapping(value = "/")
@PreAuthorize("hasRole('ROLE_group1')"+"|| hasRole('ROLE_group2')"+"|| 
hasRole('ROLE_group3')")

应用属性

azure.activedirectory.tenant-id=xxxxxxxxxxxxxxx
azure.activedirectory.client-id=xxxxxxxxxxxxxxx
azure.activedirectory.client-secret=xxxxxxxxxxxxxx
azure.activedirectory.user-group.allowed-groups=group1,group2,group3

我更新了我的POM

xml prettyprint-override"><dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-active-directory-spring-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
    <version>2.4.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.4.5</version>
</dependency>

更新POM后的新错误:

 ERROR org.springframework.boot.SpringApplication [main] Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChainProxySecurityConfigurer' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.azure.spring.aad.webapp.AADWebAppConfiguration$DefaultAADWebSecurityConfigurerAdapter': Unsatisfied dependency expressed through method 'setContentNegotationStrategy' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setAuthorizedClientRepository' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authorizedClientRepository' defined in class path resource [com/azure/spring/aad/webapp/AADWebAppConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository]: Factory method 'authorizedClientRepository' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/security/oauth2/client/OAuth2AuthorizedClientProvider

我已经更新了我的POM,现在它正在构建罚款,但在登录时,我得到AADSTS50011:请求中指定的回复URL不匹配为应用程序配置的回复URL:'18da6914-.....................................................................'...我添加了以下重定向URI:localhost:8080localhost:8080/login/oauth2/code

因为我对此完全陌生,我将感谢任何帮助。

共有2个答案

柳高卓
2023-03-14

似乎主要问题是您的Spring Boot版本。您已经指定了2.1.6。RELEASE,但较新的版本可能更合适。

这里有几个观察结果,我会接着给出一个建议的修复方法。

您添加了Spring Security 5.4。然而,x依赖项是用于Spring Boot 2.4的。十、

本教程以Spring Boot 2.3为基础。x、 Spring Security是5.3。x依赖项用于Spring Boot 2.3。十、

出现NoClassDefFoundError的原因是AADWebAppConfiguration试图查找一个在Spring Boot 2.1之后才引入的类。

我认为最好的办法是确保您的依赖项与您正在遵循的教程保持一致,或者它们是最新的依赖项。

具体来说,你有:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath />
        <!-- lookup parent from repository -->
    </parent>

除此之外:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
    <version>2.4.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.4.5</version>
</dependency>

但它们彼此不兼容。

我建议从本教程使用的Spring Boot版本开始,以使事情正常进行。

鲁俊友
2023-03-14

您的代码看起来是正确的。但是,由于错误显示"嵌套异常java.lang.IllegalStateExcture: Client id不得为空.",您需要再次检查application.properties并确保其正确。

示例需要三个依赖项(spring-boot-starter-oauth2-clientspring-boot-starter-webazure spring-boot-starter active directory),您可以尝试用更新的版本更新pom。

下面是我的代码。

主要内容:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@SpringBootApplication
public class SpringBootSampleAdApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootSampleAdApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder 
    application) {
        return application.sources(SpringBootSampleAdApplication.class);
    }

    @Configuration
    public class DataSourceConfiguration {/*creds*/}
}

控制器:

@RestController
public class HelloController {

    @PreAuthorize("hasRole('ROLE_pamela-group1')"+"|| hasRole('ROLE_pamela-group2')")
    @RequestMapping("/test")
    public String helloWorld() {
        return "Hello Users!";
    }
}

application.properties:

azure.activedirectory.tenant-id=xxxxx
azure.activedirectory.client-id=xxxxx
azure.activedirectory.client-secret=xxxxx
azure.activedirectory.user-group.allowed-groups=pamela-group1,pamela-group2

测试结果:

 类似资料:
  • 如何在Spring Security中实现基于JWT的身份验证和授权 我试图在我的Spring启动应用程序中实现基于jwt的身份验证和授权。我遵循了这里写的教程。但是它在我的应用程序中没有做任何事情。它不返回jwt令牌,而是我被验证了,我的请求得到了满足。我是Spring安全新手。这是我的代码。 我希望我的应用程序返回jwt令牌,并且使用该令牌必须授权请求。 这是我的密码。 ilter.java

  • 问题内容: 我一直在努力用Spring-Security 正确实现Stomp(websocket) 身份验证 和 授权 。 为了后代,我将回答我自己的问题以提供指导。 问题 Spring WebSocket文档(用于身份验证)看起来不清楚ATM(IMHO)。而且我不明白如何正确处理 身份验证 和 授权 。 我想要的是 使用登录名/密码对用户进行身份验证。 防止匿名用户通过WebSocket连接。

  • OAuth术语已经困扰我很久了。OAuth授权是像一些人建议的那样,还是认证? 如果我错了,请纠正我,但我一直认为授权是允许某人访问某个资源的行为,而OAuth似乎没有任何实际允许用户访问给定资源的实现。OAuth实现所讨论的都是为用户提供一个令牌(签名的,有时是加密的)。然后,每次调用都会将该令牌传递到后端服务endpoint,在后端服务endpoint上检查该令牌的有效性,这也不是OAuth的

  • 我正在实现一个基于Spring Data REST的应用程序,我想知道是否有一种优雅的方法可以使用此框架或相关框架来实现身份验证和授权规则。 对REST服务器的所有HTTP请求都必须带有身份验证标头,我需要检查它们并根据HTTP方法和经过身份验证的用户与所请求资源的关联来决定是否授权。例如,(该应用程序是电子学习系统的REST服务器),讲师只能访问他们自己的课程部分,学生只能访问他们订阅的课程部分

  • 我尝试使用flask在MongoDB中创建字段,使用下面的代码 URI中传递了正确的凭据,但我得到以下错误 OperationFailure:身份验证失败。,完整错误:{'OK':0.0,'errMsg':'Authentication Failed.','代码':18,'代码名':'AuthenticationFailed','操作时间':Timestamp(1600853835,1),'$Cl