因为要用OAuth2.0,所以我们的项目必须是一个分布式的项目,我们还需要将认证的服务和资源的服务分开。我们就重新的创建一个分布式的项目。
创建项目架构
1 创建分布式的项目,在父工程里面导入依赖
导入了springboot的依赖,还有springcloud的依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/>
</parent>
<properties>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
</properties>
<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>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
2 再创建两个服务,一个是资源服务,一个是认证服务
3 创建资源服务,导入资源服务要的依赖,oauth2的依赖,这个是和springcloud整合了
security的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
资源服务是应该有多个,现在只是写一个就可以了,因为是自己测试,导入依赖就开始配置yml了,因为这个是资源文件,资源是保存在数据库,所以在yml里面配置数据库相关的东西,端口号指定一个,因为资源服务是很多的,所以现在用端口号进行区分。
server:
port: 9002
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/security?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: '123456'
main:
allow-bean-definition-overriding: true #允许我们自己覆盖spring放入到IOC容器的对象
mybatis:
type-aliases-package: com.itheima.domain
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.itheima: debug
因为我们只是测试,所以不需要连接数据库,写一个接口,返回一句话就可以了。
这就写了一个接口了,现在我们要做的就是将这个接口给了OAuth2.0,让他进行管理。
以便其他的服务可以通过token访问我们的资源。
我们自己写一个配置类,但是要将这个配置类变为和OAuth2.0相关的,那么就要写这个注解@EnableResourceServer 开启资源服务
并且要继承人家OAuth2.0源码里面的一个类ResourceServerConfigurerAdapter
要重写人家源码里面的方法,只有重写了人家源码里面的东西,我们才可以使用OAuth2.0相关的功能。
其他的服务访问这个资源 服务的时候,会携带一个token,
* 这个token会被资源服务保存起来,那么以什么方式进行保存呢?
* 就需要我们进行配置
OAuth2.0给我们提供了很多的保存token的方式,是以接口的形式暴露,这个源码里面的接口下有很多的实现类,看我们咋选择。以下是可以选择的实现类
/**
* 指定token的持久化策略
*其他的服务访问这个资源 服务的时候,会携带一个token,
* 这个token会被资源服务保存起来,那么以什么方式进行保存呢?
* 就需要我们进行配置
* InMemoryTokenStore表示将token存储在内存
* Redis表示将token存储在redis中
* JdbcTokenStore存储在数据库中
* @return
*/
@Bean
public TokenStore jdbcTokenStore(){
return new JdbcTokenStore(dataSource);
}
我们现在选择了JdbcTokenStore() 这个类,这个需要一个参数,这个参数就是数据源,我们已经在yml里面配置了数据库的数据源,现在spring容器里面已经有这个数据源了,我们只需要将这个数据源注入到这个配置类里面就可以了,作为参数放到里面就可以了。
@Autowired
private DataSource dataSource;
@Bean
public TokenStore jdbcTokenStore(){
return new JdbcTokenStore(dataSource);
}
现在开始重写人家的方法
/**
* 指定当前资源的id和存储方案
* @param resources
* @throws Exception
*/
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("product_api").tokenStore(jdbcTokenStore());
}
resourceId()这个方法 的意思是给当前的服务起一个名字
tokenStore() 这个方法 的意思是配置当前的资源的地方
@Override
public void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
//指定不同请求方式访问资源所需要的权限,一般查询是read,其余是write。
.antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')")
.antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')")
.antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')")
.antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')")
.antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')")
.and()
.headers().addHeaderWriter((request, response) -> {
response.addHeader("Access-Control-Allow-Origin", "*");//允许跨域
if (request.getMethod().equals("OPTIONS")) {//如果是跨域的预检请求,则原封不动向下传达请求头信息
response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method"));
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
}
});
}
因为A系统和B系统是不一样的系统,所以调用需要解决跨域的问题。
response.addHeader(“Access-Control-Allow-Origin”, “*”);//允许跨域
以上的代码一般就是固定的配置,你不需要变,直接复制就可以了。
以上配置完成之后,就相当于这个服务器已经交给了OAuth2.0资源的管理。
但是还有一个问题,那就是A系统访问B系统,需要用户在B系统进行登录,意思是用户都不能在B系统登录,你拼什么让A系统访问B系统。所以我们还需要一个是B系统认证用户。
但是这个认证不是用户自己登录,这个是OAuth2.0给你验证,是A系统将token给了B系统,B系统拿到token之后,将里面的用户名密码自己拿出来进行认证,所以这个B系统的认证是OAuth2.0给你做的,你只需要进行配置就可以了。咋配置
1 确保有依赖
2 写用户的实体类
这样OAuth2.0会自动的将token里面的信息提取出来封装为用户对象进行认证
总结
1 我们创建一个资源服务,里面写一个接口,本来启动这个项目是可以访问到这个接口的,但是现在要将这个服务交给OAuth2.0管理
2 咋交给OAuth2.0管理
3 导入OAuth2.0的依赖
4 写一个配置
5 配置里面的东西需要写指定当前资源的id和存储方案,
指定不同请求方式访问资源所需要的权限,一般查询是read,其余是write。
6 这样写完之后,我们的这个资源就交给OAuth2.0了,以后要访问这个资源,必须携带token了。