springboot整合author2

author2有几个基本角色:

资源所有者:即用户
客户端:但三方应用
授权服务器:用来验证用户提供的信息是否正确,并返回一个令牌
资源服务器:提供给用户资源的服务器

授权模式:

授权码模式:功能最完整,流程最严谨的。通过客户端服务器与授权授权服务器交互。国内常见的第三方平台登入就是使用这个功能实现的。
简化模式:不需要客户端服务器的参与,直接在浏览器中向授权服务器申请令牌,一般网站是纯静态页面的,可以使用这个方法。
密码模式:直接把用户名和密码告诉客户端,客户端使用这些信息向授权服务器申请令牌。
客户端模式:客户端使用自己的名义而不是用户的名义向服务器一共申请授权。

接下来开始springboot整合author2,github:https://github.com/fengqing11/springboot-oauth2
创建项目,依赖如下:
由于springboot中的oauth协议实在spring security的基础上完成的,因此需要添加spring security依赖。

  • 令牌存储在redis缓存服务器上,同时redis具有过期功能,很适合令牌的存储,因此也加入redis的依赖。 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.sang</groupId>
    <artifactId>oauth2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>oauth2</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>
 

 配置文件:

spring.redis.database=0
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.max-wait=-1ms
spring.redis.jedis.pool.min-idle=0
 

配置授权服务器:
授权服务器和资源服务器可一是同一台服务器,也可以是不同的服务器,这里使用同一服务器。
通过不同的配置分开授权服务器和资源服务器。
继承AuthorizationServerConfigurerAdapter,完成对授权服务器的配置,然后通过@EnableAuthorizationServer注解开启授权服务器。
AuthenticationManager对象用来支持password授权模式。
RedisConnectionFactory对象用来完成redis的缓存。
UserDetailsService对象为刷新token提供支持。
authorizedGrantTypes()方法配置授权模式为password和refresh_token,其实在标准的oauth中并没有refresh_token,但是spring security中将其归为一种,因此要实现access_token的刷新就需要refresh_token。
accessTokenValiditySeconds()方法设置token的过期时间。
resourceIds()方法配置资源id。
secret()方法配置了加密后的密码,明文是123。

package org.sang.oauth2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
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;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig
        extends AuthorizationServerConfigurerAdapter {
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    RedisConnectionFactory redisConnectionFactory;
    @Autowired
    UserDetailsService userDetailsService;
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        clients.inMemory()
        .withClient("password")
        .authorizedGrantTypes("password", "refresh_token")
        .accessTokenValiditySeconds(1800)
        .resourceIds("rid")
        .scopes("all")
        .secret("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq");
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
        endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);
    }
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security)
            throws Exception {
        security.allowFormAuthenticationForClients();
    }
}
 

 配置资源服务器:
继承ResourceServerConfigurerAdapter,并使用@EnableResourceServer注解开启资源服务器配置。
resourceId()来配置资源id,这里的id和授权服务器的资源id要一样。
stateless()方法设置这些资源仅基于令牌验证。

package org.sang.oauth2;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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;

@Configuration
@EnableResourceServer
public class ResourceServerConfig
        extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(ResourceServerSecurityConfigurer resources)
            throws Exception {
        resources.resourceId("rid").stateless(true);
    }
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated();
    }
}
 

配置security:
和前面的没什么区别,唯一不同的是多了两个@bean注解,这两个Bean将注入到授权服务器中使用。
这里的HttpSecurity配置主要配置/oauth/**的URL,这一类的请求直接放行。在资源服务器配置中也有一个HttpSecurity,这里的HttpSecurity优先于资源服务器的HttpSecurity。

package org.sang.oauth2;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        return super.userDetailsService();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
        .withUser("admin")
        .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
        .roles("admin")
        .and()
        .withUser("sang")
        .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
        .roles("user");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/oauth/**").authorizeRequests()
                .antMatchers("/oauth/**").permitAll()
                .and().csrf().disable();
    }
}
 

启动服务器后POST访问:http://127.0.0.1:8080/oauth/token?username=sang&password=123&grant_type=password&client_id=password&scope=all&client_secret=123
这里参数都写在url上,方便,但也是一个post请求:

在这里插入图片描述
请求参数:

username:用户名
password:面膜
grant_type:授权模式
client_id:资源服务器id
scope:资源服务器范围
client_secret:资源服务器密码

返回内容:

access_token:就是令牌
token_type:
refresh_token:用来刷新令牌,可以用来刷新token,前提是token未过期
expires_in:token的过期时间,再次刷新可以发现实现不在是1800,他减少了
scope:

刷新token访问:http://127.0.0.1:8080/oauth/token?grant_type=refresh_token&refresh_token=6bef362e-a96c-48af-a310-b9623d7c69a4&client_id=password&client_secret=123

在这里插入图片描述

访问资源,访问:http://localhost:8080/user/hello?access_token=cf4d8b09-3fe1-4671-91f3-4703d6e75c91


在这里插入图片描述

至此,一个password模式的oauth认证体系就搭建好了。
-end-
 

猜你喜欢

转载自blog.csdn.net/xulong5000/article/details/107155321