axios自动处理token刷新_java


因为要用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

axios自动处理token刷新_axios自动处理token刷新_02


因为我们只是测试,所以不需要连接数据库,写一个接口,返回一句话就可以了。

axios自动处理token刷新_Access_03


这就写了一个接口了,现在我们要做的就是将这个接口给了OAuth2.0,让他进行管理。

以便其他的服务可以通过token访问我们的资源。

axios自动处理token刷新_axios自动处理token刷新_04


我们自己写一个配置类,但是要将这个配置类变为和OAuth2.0相关的,那么就要写这个注解@EnableResourceServer 开启资源服务

并且要继承人家OAuth2.0源码里面的一个类ResourceServerConfigurerAdapter

要重写人家源码里面的方法,只有重写了人家源码里面的东西,我们才可以使用OAuth2.0相关的功能。

其他的服务访问这个资源 服务的时候,会携带一个token,
* 这个token会被资源服务保存起来,那么以什么方式进行保存呢?
* 就需要我们进行配置

OAuth2.0给我们提供了很多的保存token的方式,是以接口的形式暴露,这个源码里面的接口下有很多的实现类,看我们咋选择。以下是可以选择的实现类

axios自动处理token刷新_axios自动处理token刷新_05

/**
     * 指定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);
    }

现在开始重写人家的方法

axios自动处理token刷新_bc_06

/**
     * 指定当前资源的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 确保有依赖

axios自动处理token刷新_bc_07


2 写用户的实体类

axios自动处理token刷新_spring_08

这样OAuth2.0会自动的将token里面的信息提取出来封装为用户对象进行认证

总结

1 我们创建一个资源服务,里面写一个接口,本来启动这个项目是可以访问到这个接口的,但是现在要将这个服务交给OAuth2.0管理
2 咋交给OAuth2.0管理
3 导入OAuth2.0的依赖
4 写一个配置
5 配置里面的东西需要写指定当前资源的id和存储方案,
指定不同请求方式访问资源所需要的权限,一般查询是read,其余是write。
6 这样写完之后,我们的这个资源就交给OAuth2.0了,以后要访问这个资源,必须携带token了。