SpringBoot2 整合OAuth2组件,模拟第三方授权访问
本文源码:GitHub·点这里 || GitEE·点这里
一、模式描述

授权服务
验证第三方服务的身份,验证邮箱用户的身份,记录和管理认证Token,为资源服务器提供Token校验。场景:第三方网站借助用户的邮箱登录,并访问邮箱账户的基础信息,头像、名称等。
资源服务
第三方服务通过邮箱账户登录后需要获取的一些信息,即理解为资源,存储邮箱账户的数据资源。
第三方服务
即借助邮箱用户的账户,快速登录第三个服务,免去繁杂的注册流程,有助于快速积累新用户。
交互流程
第三方服务给用户开放快速邮箱登录功能,引导用户调到邮箱认证服务,通过认证后返回身份令牌到第三方服务,第三方服务携带令牌访问邮箱的资源服务,获取一些基本的邮箱用户信息。
二、项目配置管理
1、案例结构

核心依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
这里有两个核心组件依赖:OAuth2组件和Security组件。
模块划分
- auth-server:授权服务
- resource-server:资源服务器
- third-server:第三个服务
2、配置描述
【授权服务】
OAuth2配置
这里的配置管理的是第三方的授权流程和发放给第三方的身份证明ClientID和密码,实际的场景就是第三方借助邮箱账号登录,首先就是向邮箱管理方提供材料,获取访问邮箱服务的身份证明,然后才能对接开放服务,这种模式在第三方对接业务中很常见。
/**
 * 模拟第三方授权配置
 */
@EnableAuthorizationServer
@Configuration
public class AuthConfig extends AuthorizationServerConfigurerAdapter {
    @Resource
    ClientDetailsService clientDetailsService;
    /**
     * 资源服务器校验Token
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security.checkTokenAccess("permitAll()").allowFormAuthenticationForClients();
    }
    /**
     * 第三方客户端请求配置,和资源服务访问的配置,不设置默认都可以访问,提供默认回调地址
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("third01")
                .secret(new BCryptPasswordEncoder().encode("third01"))
                .resourceIds("resource-01")
                .authorizedGrantTypes("authorization_code","refresh_token")
                .scopes("all")
                .redirectUris("http://localhost:8082/notify.html");
    }
    /**
     * 配置访问端点
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authorizationCodeServices(authorizationCodeServices()).tokenServices(tokenServices());
    }
    /**
     * 内存管理
     */
    @Bean
    AuthorizationCodeServices authorizationCodeServices() {
        return new InMemoryAuthorizationCodeServices();
    }
    /**
     * Token管理规则
     */
    @Bean
    AuthorizationServerTokenServices tokenServices() {
        DefaultTokenServices services = new DefaultTokenServices();
        services.setClientDetailsService(clientDetailsService);
        services.setSupportRefreshToken(true);
        services.setTokenStore(tokenStore());
        services.setAccessTokenValiditySeconds(3600);
        services.setRefreshTokenValiditySeconds(3600*7);
        return services;
    }
    @Bean
    TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }
}
通常需要数据库存储第三方信息,可以到第OAuth2开源项目中,获取表结构放到本地数据库中,然后这里换成数据源加载模式即可,简单的流程管理都在源码里写了SQL语句,数据源引入即可。
Security配置
/**
 * 模拟本地用户配置
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 密码加密方式
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    /**
     * 内存中虚拟用户和角色
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("user");
    }
    /**
     * 表单登录
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().formLogin();
    }
}
基于这里的配置管理邮箱用户的认证流程,例如使用邮箱账号密码登录验证,判断授权是否成立,这里管理的是服务本地的邮箱账号,基于数据源存储数据在下面案例中都有。
- 案例一:JWT组件管理身份验证机制
- 案例二:Shiro组件实现用户权限管理
- 案例三:Security用户安全认证流程
关于Spring框架中安全认证的相关的几个组件,在使用OAuth2之前可以先了解一下。
【资源服务】
主要功能有三块,配置第三方携带的Token身份令牌校验机制,即访问授权服务校验接口,这里是OAuth2自定义好的接口;配置resourceId资源服务的编号,用来控制第三个服务能访问的资源服务范围,属于大的权限点控制;模拟校验用户的Role角色,较精细的控制权限。
/**
 * 资源服务管理配置
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    /**
     * Token令牌校验
     */
    @Bean
    RemoteTokenServices tokenServices() {
        RemoteTokenServices services = new RemoteTokenServices();
        services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
        services.setClientId("third01");
        services.setClientSecret("third01");
        return services;
    }
    /**
     * 服务资源ID配置
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("resource-01").tokenServices(tokenServices());
    }
    /**
     * 模拟用户权限规则
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated();
    }
}
【第三方服务】
主要提供两个流程的模拟:请求授权服务获取身份令牌;携带身份令牌请求资源服务获取数据。这里则是授权码回调接口的处理方式。
@Controller
public class NotifyController {
    private static final Logger LOG = LoggerFactory.getLogger(NotifyController.class);
    @Resource
    private RestTemplate restTemplate;
    @GetMapping("/notify.html")
    public String notify(String code, Model model) {
        if (code != null) {
            MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
            map.add("code", code);
            map.add("client_id", "third01");
            map.add("client_secret", "third01");
            map.add("redirect_uri", "http://localhost:8082/notify.html");
            map.add("grant_type", "authorization_code");
            Map<String,String> resp = restTemplate.postForObject("http://localhost:8080/oauth/token", map, Map.class);
            String accessToken = resp.get("access_token");
            LOG.info("身份令牌:{}",accessToken);
            HttpHeaders headers = new HttpHeaders();
            headers.add("Authorization", "Bearer " + accessToken);
            HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
            ResponseEntity<String> entity = restTemplate.exchange("http://localhost:8081/user/resource", HttpMethod.GET, httpEntity, String.class);
            model.addAttribute("notifyMsg", entity.getBody());
        }
        return "notify";
    }
}
三、测试流程

通过上述测试流程,对比常见的第三方登录机制,理解OAuth2的授权码模式。
四、源代码地址
GitHub·地址
https://github.com/cicadasmile/middle-ware-parent
GitEE·地址
https://gitee.com/cicadasmile/middle-ware-parent
推荐阅读:编程体系整理
| 序号 | 项目名称 | GitHub地址 | GitEE地址 | 推荐指数 | 
|---|---|---|---|---|
| 01 | Java描述设计模式,算法,数据结构 | GitHub·点这里 | GitEE·点这里 | ☆☆☆☆☆ | 
| 02 | Java基础、并发、面向对象、Web开发 | GitHub·点这里 | GitEE·点这里 | ☆☆☆☆ | 
| 03 | SpringCloud微服务基础组件案例详解 | GitHub·点这里 | GitEE·点这里 | ☆☆☆ | 
| 04 | SpringCloud微服务架构实战综合案例 | GitHub·点这里 | GitEE·点这里 | ☆☆☆☆☆ | 
| 05 | SpringBoot框架基础应用入门到进阶 | GitHub·点这里 | GitEE·点这里 | ☆☆☆☆ | 
| 06 | SpringBoot框架整合开发常用中间件 | GitHub·点这里 | GitEE·点这里 | ☆☆☆☆☆ | 
| 07 | 数据管理、分布式、架构设计基础案例 | GitHub·点这里 | GitEE·点这里 | ☆☆☆☆☆ | 
| 08 | 大数据系列、存储、组件、计算等框架 | GitHub·点这里 | GitEE·点这里 | ☆☆☆☆☆ | 
SpringBoot2 整合OAuth2组件,模拟第三方授权访问的更多相关文章
- SpringBoot2 整合Kafka组件,应用案例和流程详解
		本文源码:GitHub·点这里 || GitEE·点这里 一.搭建Kafka环境 1.下载解压 -- 下载 wget http://mirror.bit.edu.cn/apache/kafka/2.2 ... 
- SpringBoot2 整合JTA组件,多数据源事务管理
		本文源码:GitHub·点这里 || GitEE·点这里 一.JTA组件简介 1.JTA基本概念 JTA即Java-Transaction-API,JTA允许应用程序执行分布式事务处理,即在两个或多个 ... 
- SpringBoot2 整合Ehcache组件,轻量级缓存管理
		本文源码:GitHub·点这里 || GitEE·点这里 一.Ehcache缓存简介 1.基础简介 EhCache是一个纯Java的进程内缓存框架,具有快速.上手简单等特点,是Hibernate中默认 ... 
- SpringBoot2 整合 Zookeeper组件,管理架构中服务协调
		本文源码:GitHub·点这里 || GitEE·点这里 一.Zookeeper基础简介 1.概念简介 Zookeeper是一个Apache开源的分布式的应用,为系统架构提供协调服务.从设计模式角度来 ... 
- SpringBoot2 整合Nacos组件,环境搭建和入门案例详解
		本文源码:GitHub·点这里 || GitEE·点这里 一.Nacos基础简介 1.概念简介 Nacos 是构建以"服务"为中心的现代应用架构,如微服务范式.云原生范式等服务基础 ... 
- Spring Security 实战干货:OAuth2第三方授权初体验
		1. 前言 Spring Security实战干货系列 现在很多项目都有第三方登录或者第三方授权的需求,而最成熟的方案就是OAuth2.0授权协议.Spring Security也整合了OAuth2. ... 
- QQ第三方授权登录OAuth2.0实现(Java)
		准备材料 1.已经备案好的域名 2.服务器(域名和服务器为统一主体或域名已接入服务器) 3.QQ号 4.开发流程:https://wiki.connect.qq.com/%E5%87%86%E5%A4 ... 
- SpringBoot基于JustAuth实现第三方授权登录
		1. 简介 随着科技时代日渐繁荣,越来越多的应用融入我们的生活.不同的应用系统不同的用户密码,造成了极差的用户体验.要是能使用常见的应用账号实现全应用的认证登录,将会更加促进应用产品的推广,为生活 ... 
- OAuth2.0认证和授权原理
		什么是OAuth授权? 一.什么是OAuth协议 OAuth(开放授权)是一个开放标准. 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和密 ... 
随机推荐
- 怎么在word里编辑插入数学公式?
			大学时代我们都有一个共同的噩梦--高数.每次上完高数课都有一些数学公式.可是我们最难的就是想用电脑在word中做笔记的时候该怎样用word插入公式.Word中自有的公式太少,新公式又太难输入.这也是一 ... 
- 堆的数据结构java
			public class MaxHeap { private int[] data; private int count; private int capacity; public MaxHeap(i ... 
- shipyard中文版安装教程(附安装脚本)
			一. Docker Shipyard是什么 ? shipyard是一个开源的docker管理平台,其特性主要包括: 支持节点动态集群,可扩展节点的规模(swarm.etcd方案) 支持镜像管理.容器管 ... 
- 【树形dp】【CF161D】distance on a tree + 【P1352】没有上司的舞会
			T1题面: 输入点数为N一棵树 求树上长度恰好为K的路径个数 (n < 1e5, k < 500) 这是今天的考试题,也是一道假的紫题,因为我一个根本不会dp的蒟蒻只知道状态就一遍A掉了- ... 
- 项目、地铁/公交、游戏签到、项目上线后发现新bug该怎么处理
			项目:1.提前分配好业务(每个人该干什么 )2.提前召开会议3.提前挑好人4.准备项目思维导图5.提前审阅项目6.为确保项目按期交付 把控好时间7.给员工提前打好招呼 (提醒加班)8.建立好安全机制9 ... 
- JZOJ 2020.10.6 提高B组反思
			JZOJ 2020.10.6 提高B组反思 T1 NYG的动态数点 最简单的一题 很容易想到\(O(n)\)的做法 枚举最小的那个数,即\(a_k\) 然后向左和向右扩展 然后可以直接从右端点+1继续 ... 
- day4(JWT介绍)
			1.JWT介绍 1.1jwt原理 最简单理解:jwt本质就是, 把用户信息通过加密后生成的一个字符串 JWT的原则是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户 { "Use ... 
- 定时器:Django-crontab
			定时器是平时编程中比较常用的,今天分享一个Django里非常好用又简单的定时亲:Django-crontab.这个真的是非常的简单好用,比celery+Django执行周期任务简单的多 首先下载dja ... 
- 强大的拉姆表达式转Sql 类库 - SqlSugar 隐藏功能之Lambda
			使用场景 1.Lambda to sql 一直是ORM中最难的功能之一,如果有现成的解析库那么自已写一个ORM难度将大大降低 2.通过Lambda作为KEY进行缓存操作,特别是仓储模式想要拿到表达式进 ... 
- 第7.21节 Python抽象类—register注册虚拟子类
			上两节介绍了Python抽象类的真实子类的定义和使用,本节介绍另一种抽象类的实现方法:虚拟子类方法. 一. 相关概念 虚拟子类是将其他的不是从抽象基类派生的类"注册"到抽象基 ... 
