spring cloud oauth2 token获取后通过zuul网关访问资源服务器出现:{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
},求大神帮帮忙
项目技术
springboot2.1+spring cloud2.1+oauth2
spring-cloud-demo-eureka:服务注册中心
spring-cloud-demo-auth:授权服务
spring-cloud-demo-provider-auth:普通服务
spring-cloud-demo-zuul:网关
项目截图
运行截图
获取token:
调用:
相关代码片段
授权服务代码:
package com.springcloud.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
RedisConnectionFactory redisConnectionFactory;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
String finalSecret = "{bcrypt}" + new BCryptPasswordEncoder().encode("123456");
// 配置两个客户端,一个用于password认证一个用于client认证
clients.inMemory()
.withClient("client_2")
//.resourceIds(Utils.RESOURCEIDS.ORDER)
.authorizedGrantTypes("client_credentials","password", "refresh_token")
.scopes("server")
//.authorities("oauth2")
.secret(finalSecret)
.and()
.withClient("client_1")
//.resourceIds(Utils.RESOURCEIDS.ORDER)
.authorizedGrantTypes("client_credentials", "refresh_token")
.scopes("select")
//.authorities("oauth2")
.secret(finalSecret);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// 配置授权endpoint
endpoints.tokenStore(new MyRedisTokenStore(redisConnectionFactory))
.authenticationManager(authenticationManager)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
// 允许表单认证
security.allowFormAuthenticationForClients().tokenKeyAccess("permitAll()")//公开/oauth/token的接口
.checkTokenAccess("isAuthenticated()");
}
}
package com.springcloud.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean
@Override
protected UserDetailsService userDetailsService() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String finalPassword = "{bcrypt}"+bCryptPasswordEncoder.encode("123456");
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user_1").password(finalPassword).authorities("USER").build());
manager.createUser(User.withUsername("user_2").password(finalPassword).authorities("USER").build());
return manager;
}
@Bean
PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
AuthenticationManager manager = super.authenticationManagerBean();
return manager;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().anyRequest()
.and()
.authorizeRequests()
.antMatchers("/user/**").permitAll();
}
}
配置文件:application.yml
#该文件等同于application.properties
spring:
application:
name: auth-demo
# datasource:
# url: jdbc:mysql://localhost:3306/zuul-auth?useUnicode=true&characterEncoding=utf-8
# username: root
# password: 123456
# driver-class-name: com.mysql.jdbc.Driver
redis:
host: 127.0.0.1
port: 6379
#password: 123456
server:
port: 9030
# servlet:
# context-path: /uaa
eureka:
client:
#此项目不作为客户端注册,若是未禁用eureka服务注册中心的客户端注册行为,需提供service-url注册中心地址:
register-with-eureka: true
#注册中心地址
service-url:
#开启权限验证后Eureka地址为 用户名:密码@地址:端口号,如未开启权限验证则直接使用 地址:端口号
defaultZone: http://root:root@localhost:8761/eureka
普通服务:
package com.springcloud.demo.config;
import feign.RequestInterceptor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
@EnableOAuth2Client
@EnableConfigurationProperties
@Configuration
public class OAuth2ClientConfig {
@Bean
@ConfigurationProperties(prefix = "security.oauth2.client")
public ClientCredentialsResourceDetails clientCredentialsResourceDetails() {
return new ClientCredentialsResourceDetails();
}
@Bean
public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oauth2ClientContext,
ClientCredentialsResourceDetails resource) {
return new OAuth2FeignRequestInterceptor(oauth2ClientContext, resource);
}
@Bean
public OAuth2RestTemplate clientCredentialsRestTemplate() {
return new OAuth2RestTemplate(clientCredentialsResourceDetails());
}
}
package com.springcloud.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)//EnableGlobalMethodSecurity开户方法级别的保护
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()//去掉获取token会被拦截
.antMatchers("/auth/**").permitAll()//开放的资源不用授权
.antMatchers("/user/**").authenticated();
}
}
配置文件:application.yml
#该文件等同于application.properties
spring:
application:
name: provider-demo
datasource:
url: jdbc:mysql://localhost:3306/pub_web?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
jpa:
database: MYSQL
show-sql: true
server:
port: 8078
mybatis:
mapper-locations : classpath*:/mybatis-mapping/*Mapper.xml
type-aliases-package : com.springcloud.demo.model
eurekaServer:
host: localhost
port: 8761
user: root
password: root
eureka:
client:
#此项目不作为客户端注册,若是未禁用eureka服务注册中心的客户端注册行为,需提供service-url注册中心地址:
register-with-eureka: true
#注册中心地址
service-url:
#开启权限验证后Eureka地址为 用户名:密码@地址:端口号,如未开启权限验证则直接使用 地址:端口号
defaultZone: http://${eurekaServer.user}:${eurekaServer.password}@localhost:8761/eureka,http://${eurekaServer.user}:${eurekaServer.password}@localhost:8762/eureka,http://${eurekaServer.user}:${eurekaServer.password}@localhost:8763/eureka
security:
oauth2:
client:
clientId: client_2
id: client_2
clientSecret: 123456
userAuthorizationUri: http://localhost:9030/oauth/authorize
accessTokenUri: http://localhost:9030/oauth/token
grantType: client_credentials
scope: server
你试试access token 前面加个bearer , 有个空格
解决了吗
Zuul配置时有一个敏感Header的设置,默认情况下会过滤Cookie、Set-Cookie和Authorization这3个。通过Zuul调用微服务时就会Authorization给过滤掉,所以微服务将收不到token,从而抛出未认证异常错误。只需要在Zuul服务器中重设一下敏感Header就可以了: