最近在学习微服务相关的知识及各种框架的使用,在搭建的过程中,遇到了不少问题,但是都没有记录下来,导致过一段时间后,就没有什么印象了.. 所以决定在掘金写文章。 一是为了记录自己在写代码过程中的知识点以及解决的问题,方便查阅; 二是为了能与其它朋友一起讨论,可以吸收不同思想及不同方案,扩展思路。
标题之所以为 Spring Cloud Security ,是因为想要写 Spring Cloud 相关的一系列技术。而 Spring Cloud 依赖 Springboot , security 还是 Spring Security 模块的东西,本质上没有太大的区别。
在写的过程中,遇到自己不熟悉或没有把握的概念及知识,会谨慎的求证。也会尽量保证发布的任何代码都是可运行的。 但是由于自己技术能力有限,难免会有错误,包括但不限于 拼写错误 、 代码错误 、 有代码洁癖的人看着缩进不舒服 、 概念理解有偏差 、 代码不够优雅 等等,希望各位可以不吝指教,不喜勿喷~
阮一峰老师的OAuth2.0介绍
microservice ,作为所有服务的 parent , 同时引入依赖 <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<spring.cloud.dependencies.version>Greenwich.RELEASE</spring.cloud.dependencies.version>
<spring-security-oauth2-autoconfigure.version>2.1.5.RELEASE</spring-security-oauth2-autoconfigure.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>${spring-security-oauth2-autoconfigure.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
复制代码
uaa-service ,作为认证授权服务,引入依赖 <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
</dependencies>
复制代码
spring-cloud-starter-oauth2 这个依赖应该已经包含了 spring security 相关的 jar ,但是 spring-cloud-dependencies 版本为 Greenwich.RELEASE 时, spring-security-oauth2-autoconfigure 子module中引入的版本一直是 2.1.0.M4 ,不管是重新import还是删除本地 maven repository 都不管用, 在官方的 issue 中也有人遇到的相同的问题 , 所以以上依赖暂时使用单独引入 spring-security-oauth2-autoconfigure , version 还必须在子module中指定,不知你们是否也碰到这种问题.
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
super.configure(security);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client-id")
.secret(passwordEncoder.encode("client-secret"))
.scopes("read", "write")
.authorizedGrantTypes("password", "refresh_token")
.authorities("user:view");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(tokenStore());
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
}
复制代码
@EnableAuthorizationServer 注解告诉 Spring 激活authorization server @Configuration 注解的实现了 AuthorizationServerConfigurer 接口的类表明这是一个authorization server配置类。 AuthorizationServerConfigurerAdapter 是 Spring 提供的默认实现 AuthorizationServerConfigurer 接口的类,里面都是空方法 authenticationManager ,这是 Spring 默认提供的, 如果需要使用 password 模式,必须显示地配置 endpoints.authenticationManager(authenticationManager) passwordEncoder ,用于用户登录时密码校验以及创建用户时密码的加密 tokenStore 这里暂时使用 InMemoryTokenStore , Spring 同时也提供了如下几种存储 token 方式
ClientDetailsServiceConfigurer 是配置authorization server颁发的client的凭证
client.inMemory() 是在内存中存储client信息 withClient 和 secret 是client的 username 和 password scopes 是授权范围,例如该client可以进行读和写 authorizedGrantTypes 是配置授权方式, 可以是 OAuth2.0 中支持的方式,也可以是自定义的 @Configuration
@EnableGlobalMethodSecurity(proxyTargetClass = true, prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin")
.password(passwordEncoder().encode("password"))
.roles("ADMIN");
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
复制代码
@EnableGlobalMethodSecurity(proxyTargetClass = true, prePostEnabled = true) 开启方法级别权限验证 AuthenticationManagerBuilder 在内存中配置一个用户,用于 password 模式获取 token BCryptPasswordEncoder 配置加密实现类 以上项目启动完成之后,启动项目, spring security 会为我们提供几个 endpoint , 其中一个就是获取token的: /oauth/token 。使用的http请求工具是 postman
如上图所示,输入之后,会把之前配置的 client 的 username 和 password 的 base64 编码放在 http header 中
在 http body 中输入
发送请求之后,得到响应, 其中的 access_token 就是我们后续请求接口使用的令牌
以上就是利用 spring security 简单地搭建authorization server, 可以看到还是蛮方便的。但是如果是用在生产环境,还远不够,例如用户信息、client信息、token信息的持久化,各种异常的处理,资源服务器的配置等等,在后续的文章也会不断的完善,感谢!