我正在将Monolith Java/Spring服务器重写为MicroService,同时向客户机公开相同的API接口,这样他们就不会注意到任何更改。
在Monolith服务器中,我们使用Spring-Security
和Spring-Security-OAuth2
。
第一部分是创建一个基于Java的API-Gateway,它将处理所有身份验证/授权作为通往Monolith服务器的隧道。
创建新的微服务(使用spring Initializer)后,我尝试将spring security配置为使用以下方式将所有身份验证隧道到Monolith服务器:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final AuthenticationProvider authenticationProvider;
public WebSecurityConfig(AuthenticationProvider authenticationProvider) {
this.authenticationProvider = authenticationProvider;
}
}
@Component("authenticationProvider")
public class CustomRemoteAuthenticationProvider extends RemoteAuthenticationProvider {
@Override
@Autowired
@Qualifier("remoteAuthenticationManager")
public void setRemoteAuthenticationManager(RemoteAuthenticationManager remoteAuthenticationManager) {
super.setRemoteAuthenticationManager(remoteAuthenticationManager);
}
}
@Service("remoteAuthenticationManager")
public class CustomRemoteAuthenticationManager implements RemoteAuthenticationManager {
@Override
public Collection<? extends GrantedAuthority> attemptAuthentication(String username, String password) throws RemoteAuthenticationException {
... here I do an HTTP call to the Monolith `/oauth/login`
}
}
当我访问Spring安全的http://localhost:8080/login
页面时,我可以成功登录,请求被隧道到我们的Monolith服务器。
当我尝试配置OAuth2
资源服务器时,问题就出现了,因为我们的客户端当前正在使用POST-tooauth/token进行身份验证,头中有一些基本身份验证:
Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
注意:基本的令牌是所有客户端的静态令牌(我知道它没有任何价值,但这是它目前的实现方式,我试图实现一个完全兼容的API-Gateway)
这允许他们与该endpoint通信,并获取正文中用户/密码的有效令牌(即application/x-www-form-urlencoded):
password=somepassword&username=user@example.com&grant_type=password&scope=read%20write
问题是Spring Security返回一个
401未授权的
调用,甚至不允许请求输入/oauth/log
路由并进行远程身份验证。
我找不到将基本身份验证隧道到整体服务器的方法,所以
/oauth/log
实际上将通过远程基本身份验证对整体进行身份验证,成功后,它将充当隧道,并将主体本身传递到整体/oauth/log
终端(正如我在上面的WebSecurityConfig
中所做的那样)
任何指示都将不胜感激。提前谢谢!
我正在做一个类似的项目,我想我可以帮你一些指导。
OAuth2是基于令牌的安全授权和身份验证,我们可以分为四个组件:
在您的情况下,受保护的资源是您希望在微服务体系结构中打破的整体。
从spring intilizr创建SpringCloud项目确保存在以下依赖项:
<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>
之后,在oAuth2服务的主类中,您需要添加两个注释。@EnableResourceServer
用于告诉您的微服务是受保护的资源。@EnableAuthorizationServer
将告诉Spring Cloud,服务将用作OAuth2Service。下面是代码片段:
@SpringBootApplication
@EnableResourceServer
@EnableAuthorizationServer
public class Oauth2ServerApplication {
public static void main(String[] args) {
SpringApplication.run(Oauth2ServerApplication.class, args);
}
}
我们创建一个将公开用户信息的endpoint。此endpoint将被其他服务调用。这就是为什么我们用@EnableResourceServer
注释这个应用程序的原因。下面是返回用户信息的restendpoint:
@RestController
@RequestMapping("/user")
public class UserRestController {
@GetMapping(produces="application/json")
public Map<String,Object> getUser(OAuth2Authentication user){
Map<String,Object> userInfo = new HashMap<>();
userInfo.put("user",user.getUserAuthentication().getPrincipal());
userInfo.put("authorities", user.getUserAuthentication().getAuthorities());
return userInfo;
}
}
现在,您将在oauth2服务中注册应用程序。您将定义将访问受保护资源的应用程序。您将创建一个配置类,该类将定义什么应用程序可以使用您的服务。
@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
OAuth2ConfigParameters oauth2ConfigParameters;
@Bean
public OAuth2ConfigParameters oAuth2ConfigParameters() {
return new OAuth2ConfigParameters();
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("your application")
.secret("your password")
.authorizedGrantTypes( "refresh_token","password","client_credentials")
.scopes("webclient","mobileclient");
}
}
您需要定义应用程序的用户和角色。如果您已经使用SpringBoot进行了安全保护,那么这是很熟悉的。检查下面的代码段:
@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();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("you user")
.password(passwordEncoder().encode("your password"))
.roles("your role");
}
}
最后,请与邮递员一起检查您是否可以从oAuth2服务中检索令牌。
HttpMethod:POST,URL:http://localhost:application-端口/oauth/token
授权类型:基本,用户名:客户端id,密码:客户端密码
Grant:密码
范围:网络客户端
用户名:您的用户名
密码:您的密码
在检索令牌之后,测试您是否可以访问该令牌以及您公开用户信息的endpoint的URL。
HttpMethod:Get,URL:localhost:application-port/user
授权:承载,令牌:生成令牌
首先,您需要将Spring Security性和OAuth2 JAR添加到您试图保护的服务中。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
下一步是应用程序。我们配置您的oauth2服务的服务点。之所以这样做,是因为monolith是一个受保护的服务,每次请求到来时,您都希望检查请求的令牌是否有效。
security:
oauth2:
resource:
userInfoUri: http://localhost:oauth2-app-port/auth/user
在这之后,别忘了添加@EnableResourceServer
,它使monolith成为受保护的资源。
@SpringBootApplication
@EnableResourceServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
之后,我们指定我们想要的限制。我在下面提供了限制只对经过身份验证的用户进行访问的示例。
@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
您的用户通过OAuth服务进行身份验证,并拥有生成的令牌。使用生成的令牌通过网关服务器向monolith发送请求。网关试图通过传播从请求中接收的令牌来访问整体。整体检查令牌是否有效。
下面是我的微服务架构与zuul网关服务器和oauth2服务器的链接:https://github.com/rshtishi/payroll.如果您想查看更多详细信息,可以查看它。
我正在尝试使用OAuth2实现开发一个带有Spring Security性的rest api。但是如何删除基本身份验证呢。我只想向body发送用户名和密码,并在postman上获取令牌。 要删除基本身份验证,并从邮递员的get token中发送body标记中的用户名密码吗 我遇到了一些问题{"错误":"未经授权","error_description":"没有客户端身份验证。尝试添加适当的身份验证
但我对spring-boot/java还是个新手...有谁能帮我把这条路走对吗? 多谢了。
问题是当我尝试验证: 正文: 我总是有一个401错误状态,因为我的自定义入口点。在我看来,spring security并没有调用Authentication-Manager。我错过什么了吗?
我一直在努力遵循这个教程: https://www.baeldung.com/spring-security-basic-authentication 我创建了几个restendpoint,如下所示: 现在的问题是,每当我试图发送POST请求时,我都会得到以下错误消息: HTTP状态401-访问此资源需要完全身份验证 我尝试了两种方法来发送请求,一种是通过邮递员 1.1 401 set-cooki
问题内容: 从HttpClient 4.3开始,我一直在使用HttpClientBuilder。我正在连接到具有基本身份验证的REST服务。我将凭据设置如下: 但是,这不起作用(我正在使用的REST服务返回401)。怎么了? 问题答案: 从此处的 抢先身份验证 文档中: http://hc.apache.org/httpcomponents-client- ga/tutorial/html/aut
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd“>