Spring boot + oauth2:访问此资源需要完全身份验证
Posted
技术标签:
【中文标题】Spring boot + oauth2:访问此资源需要完全身份验证【英文标题】:Spring boot + oauth2 : Full authentication is required to access this resource 【发布时间】:2018-09-11 02:03:20 【问题描述】:我正在尝试使用 spring boot、spring cloud security 和 spring cloud oauth2 实现身份验证服务器。
当我尝试从邮递员那里点击 http://localhost:8080/auth/oauth/token 时,我遇到了错误
“错误”:“未经授权”, "error_description": "访问此资源需要完全身份验证"
下面是我的 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>
<groupId>com.teckink.tp</groupId>
<artifactId>tp-auth-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>tp-auth-server</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.M9</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>$spring-cloud.version</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
Starter(Main) 类:
package com.teckink.tp.authserver;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
@EnableResourceServer
@EnableAuthorizationServer
public class App
@RequestMapping(value = "/user" , produces = "application/json")
public Map<String, Object> user(OAuth2Authentication user)
Map<String, Object> userInfo = new HashMap<>();
userInfo.put("user", user.getUserAuthentication().getPrincipal());
userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));
return userInfo;
public static void main(String[] args)
SpringApplication.run(App.class, args);
OAuth2Config 类,它定义了客户端和它的秘密:
package com.teckink.tp.authserver.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
clients.inMemory()
.withClient("eagleeye")
.secret("thisissecret")
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
.scopes("webclient", "mobileclient");
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
WebSecurityConfigurer 类,它定义了内存中的用户、密码和角色:
package com.teckink.tp.authserver.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
@Override
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception
return super.userDetailsServiceBean();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth
.inMemoryAuthentication()
.withUser("john.carnell").password("password1").roles("USER")
.and()
.withUser("william.woodward").password("password2").roles("USER", "ADMIN");
我正在从 POSTMAN 调用 Rest API,如下所示- 请求身份验证屏幕显示如下:
请求表单数据如下
【问题讨论】:
如果可能,请将可重现的示例项目上传到 GitHub。 @Prithvi - 你认为你可以帮助我吗 - ***.com/questions/53090739/… @KyleAnderson - 你能帮我吗 - ***.com/questions/53090739/… 【参考方案1】:我注意到您的授权类型在您的帖子中列为“密码”而不是“密码” 您能否更正一下并再试一次?
【讨论】:
我把它改成了“密码”。仍然出现同样的错误【参考方案2】:在您运行的示例应用程序中,您会遇到以下异常
java.lang.IllegalArgumentException: 没有映射 PasswordEncoder 对于 id "null"
在 spring-security-core:5.0 中,默认 PasswordEncoder 构建为 DelegatingPasswordEncoder。因此,当您将用户存储在内存中时,您是以纯文本形式提供密码,然后当您尝试从 DelegatingPasswordEncoder 检索编码器以验证它找不到的密码时。
更多详情见此链接Password Encoding
为了解决这个问题,对于生产实现,您应该激活BCryptPasswordEncoder
的实例
对于开发,您可以尝试以下更改,以便通过将noop
添加到密码值来覆盖密码编码。这将通过激活NoOpPasswordEncoder
而不是默认的DelegatingPasswordEncoder
来处理密码,并将您的密码视为纯文本。
OAuth2Config 类
clients.inMemory()
.withClient("eagleeye")
.secret("noopthisissecret")
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
.scopes("webclient", "mobileclient");
WebSecurityConfigurer 类
auth
.inMemoryAuthentication()
.withUser("john.carnell"). password("nooppassword1").roles("USER")
.and()
.withUser("william.woodward").password("nooppassword2").roles("USER", "ADMIN");
现在,当您从 Postman 尝试时,您将能够生成令牌
编辑
带有工作演示的 Github 项目 here
【讨论】:
我在控制台中没有收到任何错误。此外,我在密码和密码中添加了 noop,但仍然得到相同的响应错误:“访问此资源需要完全身份验证”。 已经上传了一个 github 项目的链接。查看与您使用的代码库有什么不同。 我打错了端点:localhost:8080/auth/oauth/token。将其更改为localhost:8080/oauth/token,然后我收到了您上面提到的错误。我通过前缀 noop 解决了这个错误 @Chids - 你能在这方面取悦我吗 - ***.com/questions/53090739/…【参考方案3】:这里发生了同样的事情很奇怪。我通过使用 curl 命令解决了它。
curl -v -X POST http://url:8080/api/oauth/token -u "yourclientid:yourclient_secret" -d "grant_type=password" -d "username=yourusername" -d "password=yourpassword"
或者 如果您想在邮递员中使用它,请转到 Authorization --> 选择类型 OAUTH2 --> Get Access Token enter image description here
【讨论】:
【参考方案4】:我有同样的问题。 url错了,改成http://localhost:8080/oauth/token就OK了。 我从书中得到了这个样本,它给出了错误的 url。只需删除“/ auth”
【讨论】:
【参考方案5】:在阅读 John Carnell 的 Spring Microservices in Action 时,以下更改为我解决了这个问题。
更改了以下属性
application.yml
server:
contextPath: /auth
到
server:
servlet:
context-path: /auth
我还在每个秘密/密码中添加了 noop,现在它可以工作了!
WebSecurityConfigurer.java
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.inMemoryAuthentication()
.withUser("john.carnell").password("nooppassword1").roles("USER")
.and()
.withUser("william.woodward").password("nooppassword2").roles("USER", "ADMIN");
OAuth2Config.java
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
clients.inMemory()
.withClient("eagleeye")
.secret("noopthisissecret")
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
.scopes("webclient", "mobileclient");
我正在使用 Spring Cloud Hoxton SR11
【讨论】:
以上是关于Spring boot + oauth2:访问此资源需要完全身份验证的主要内容,如果未能解决你的问题,请参考以下文章
带有 Spring Boot REST 应用程序的 OAuth2 - 无法使用令牌访问资源
带有加密 JWT 访问令牌的 Spring Boot OAuth2
无法使用 access_token 访问资源:spring boot Oauth2
Spring Boot 2 OAuth2 资源服务器不访问授权服务器进行访问令牌验证
Spring Boot:Oauth2:访问被拒绝(用户是匿名的);重定向到身份验证入口点
使用 spring-boot-starter-oauth2-client 检索 OAuth2 3-legged 身份验证的访问令牌