使用Springboot搭建OAuth2.0 Server的方法示例

OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。

本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749。

OAuth 简介

OAuth 是由 Blaine Cook、Chris Messina、Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全、开放的标准。

基于 OAuth 认证授权具有以下特点:

  • 安全。OAuth 与别的授权方式不同之处在于:OAuth 的授权不会使消费方(Consumer)触及到用户的帐号信息(如用户名与密码),也是是说,消费方无需使用用户的用户名与密码就可以申请获得该用户资源的授权。
  • 开放。任何消费方都可以使用 OAuth 认证服务,任何服务提供方 (Service Provider) 都可以实现自身的 OAuth 认证服务。
  • 简单。不管是消费方还是服务提供方,都很容易于理解与使用。

OAuth 的解决方案如下图所示。

图 1. OAuth Solution

如 图 1 所示 OAuth 解决方案中用户、消费方及其服务提供方之间的三角关系:当用户需要 Consumer 为其提供某种服务时,该服务涉及到需要从服务提供方那里获取该用户的保护资源。OAuth 保证:只有在用户显式授权的情况下(步骤 4),消费方才可以获取该用户的资源,并用来服务于该用户。

从宏观层次来看,OAuth 按以下方式工作:

  • 消费方与不同的服务提供方建立了关系。
  • 消费方共享一个密码短语或者是公钥给服务提供方,服务提供方使用该公钥来确认消费方的身份。
  • 消费方根据服务提供方将用户重定向到登录页面。
  • 该用户登录后告诉服务提供方该消费方访问他的保护资源是没问题的。 前提

阅读本文之前,你需要了解:

  • Spring Boot
  • Spring MVC
  • Spring Security
  • Google 浏览器插件Postman

pom.xml文件如下

<?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>cn.iigrowing.study.oauth2</groupId>
 <artifactId>demo01</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>my.oauth01</name>
 <description>Demo project for Spring Boot</description>

 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>1.5.2.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</artifactId>
 </dependency>

 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>

 <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>
 </dependency>

 </dependencies>

 <build>
 <plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 </plugin>
 </plugins>
 </build>

</project>

本项目需要添加的依赖非常简单,一共只有两个,一个是Spring Web,另一个是Spring OAuth2。

接下来是本文的核心,一共三个配置类。

SecurityConfig

package cn.iigrowing.study.oauth2.demo01;

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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

 @Override
 protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 auth.inMemoryAuthentication()
 .withUser("user").password("123456").authorities("ROLE_USER");
 }

 @Override
 protected void configure(HttpSecurity http) throws Exception {
 http.httpBasic()
 .and().csrf().disable()
 .authorizeRequests()
 .antMatchers("/login").permitAll()
 .anyRequest().authenticated()
 .and()
 .formLogin()
 .and()
 .logout().permitAll();
 }

 @Override
 @Bean
 public AuthenticationManager authenticationManagerBean() throws Exception {
 return super.authenticationManagerBean();
 }

}

此处主要做了两件事情:

配置系统用户,这里使用内存存储,添加了用户名为 user ,角色为 USER 的用户

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  auth.inMemoryAuthentication()
    .withUser("user").password("123456").authorities("ROLE_USER");
}

配置了默认表单登陆以及禁用了 csrf 功能,并开启了 httpBasic 认证

@Override
  protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic()
      .and().csrf().disable()
      .authorizeRequests()
      .antMatchers("/login").permitAll()
      .anyRequest().authenticated()
      .and()
      .formLogin()
      .and()
      .logout().permitAll();
  }

AuthorizationServerConfig

package cn.iigrowing.study.oauth2.demo01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

 @Autowired
 @Qualifier("authenticationManagerBean")
 private AuthenticationManager authenticationManager;

 @Override
 public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
 clients.inMemory()
 .withClient("client").secret("123456").scopes("read")
 .authorizedGrantTypes("authorization_code")
 .redirectUris("https://www.getpostman.com/oauth2/callback");
 }

 @Override
 public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
 endpoints.authenticationManager(authenticationManager);
 }

}

这个类是OAuth2认证的核心配置类,在这个类中,配置了OAuth Client的信息,这里有几个地方需要注意:

  • @EnableAuthorizationServer 这个注解告诉 Spring 这个应用是 OAuth2 的授权服务器
  • 必须配置 authorizedGrantTypes

,它代表了OAuth Client允许认证的类型,其值主要有:

  • authorization_code
  • password
  • client_credentials
  • implicit refresh_token

这个配置项接受的类型是个数组,允许配置多个;关于这几种类型的区别,请查看这里不再赘述

redirectUris 关于这个配置项,是在 OAuth2协议中,认证成功后的回调地址,因为稍后我们会使用 Postman 作为测试工具,故此处值固定为 https://www.getpostman.com/oauth2/callback ,此值同样可以配置多个 ResourceServerConfig

package cn.iigrowing.study.oauth2.demo01;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
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) {
resources.resourceId(“users-info”);

}

@Override
public void configure(HttpSecurity http) throws Exception {

http

.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)

.and()

.requestMatchers()

.antMatchers(“/users/**”)

.and().authorizeRequests()

.antMatchers(“/users/**”)

.authenticated();

}
}

这个类表明了此应用是OAuth2 的资源服务器,此处主要指定了受资源服务器保护的资源链接,我们将提供以下的资源:

@RestController
@RequestMapping("users")
public class UserController {

  @GetMapping("me")
  public Principal me(Principal principal) {
    return principal;
  }
}

注:

资源服务器可以和授权服务器是同一个,也可以分开部署

最后,我们还需添加 application.yml , 配置资源服务器的filter的顺序

server:
 port: 8043
 context-path: /uaa
logging:
 level:
  org.springframework.security: DEBUG
spring:
 application:
  name: oauth-server
security:
 oauth2:
  resource:
   serviceId: ${PREFIX:}resource
   # refer to: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.5-Release-Notes#oauth-2-resource-filter
   filter-order: 3

此处的 filter-order 非常重要,因为自Spring Boot 1.5.* 之后,resource server 的 filter 的顺序默认在 basic authentication filter chain 之后,所以如果不配置此项,将会导致使用 access_token 访问 resource server 的时候返回 401 状态码。

好了,所有的开发工作已经完成,无需任何其他配置,现在我们启动服务器,并通过 Postman 访问 http://localhost:8043/uaa/users/me

因为现在还没通过认证,所以服务器将返回 401 的状态码,并返回以上的错误信息。

现在我们使用 Postman 来获取 access_token ,首先选择 Authorization Tab, 然后选择 TypeOAuth2.0 ,最后点击 Get New Access Token 按钮:

此时将弹出以下界面:

我们填入对应的信息:

  • Token Name: access_token
  • Auth URL: http://localhost:8043/uaa/oauth/authorize
  • Access Token URL: http://localhost:8043/uaa/oauth/token
  • Client ID: client
  • Client Secret: 123456
  • Grant Type: Authorization Code

此处配置的client相关信息对应了我们在 AuthorizationServerConfig 里面的配置,之前配置的回调地址也来自于此处的 Callback URL

接下来点击 Request Token 按钮,在弹出的登陆界面中输入我们之前在 SecurityConfig 中配置的用户信息,选择 Approval 并点击 Authorize 按钮,即可获取 access_token :

到这里我们就成功的获取了 token,此时再次调用 users/me Api,如无意外,将会得到以下的结果:

这个项目实现了以下的功能:

  • 使用 JWT Token进行认证
  • 多Resource Sever
  • 使用数据库存储用户以及OAuth Client信息
  • 提供相关的Rest API进行用户及 Client的管理
  • 结合了Spring Cloud

源代码:my.oauth01

小结

OAuth 协议作为一种开放的,基于用户登录的授权认证方式,目前互联网很多 Open API 都对 OAuth 提供了支持,这包括 Google, Yahoo,Twitter 等。本文以 Google 为例子,介绍了 Java 桌面程序如何开发 OAuth 认证应用。在开发桌面应用访问 Web 资源这样一类程序时,一般通行的步骤是:使用 OAuth 做认证,然后使用获得的 OAuth Access Token,通过 REST API 访问用户在服务提供方的资源。

事实上,目前 OAuth 正通过许多实现(包括针对 Java、C#、Objective-C、Perl、PHP 及 Ruby 语言的实现)获得巨大的动力。大部分实现都由 OAuth 项目维护并放在 Google 代码库 (http://oauth.googlecode.com/svn/) 上。开发者可以利用这些 OAuth 类库编写自己需要的 OAuth 应用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • springboot+Oauth2实现自定义AuthenticationManager和认证path

    本人在工作中需要构建这么一个后台框架,基于springboot,登录时认证使用自定义AuthenticationManager:同时支持Oauth2访问指定API接口,认证时的AuthenticationManager和登录规则不同.在研究了源码的基础上参考很多文章,目前基本得以解决. @Configuration public class OAuth2Configuration { @SpringBootApplication @RestController @EnableResourceSe

  • 详解Spring Boot Oauth2缓存UserDetails到Ehcache

    在Spring中有一个类CachingUserDetailsService实现了UserDetailsService接口,该类使用静态代理模式为UserDetailsService提供缓存功能.该类源码如下: CachingUserDetailsService.java public class CachingUserDetailsService implements UserDetailsService { private UserCache userCache = new NullUserC

  • 详解Springboot Oauth2 Server搭建Oauth2认证服务

    本教程源码 https://github.com/bestaone/HiAuth 源码比较全面,教程我就只介绍关键代码了,喜欢的点个star,谢谢! 关键词 微服务认证 Oauth2 认证中心 springboot spring-cloud-starter-oauth2 集成Oauth2 Oauth2 客户端 介绍 这里我将介绍两个部分 Oauth2 server 的开发 (hi-auth-web模块) Oauth2 client 的开发 (hi-mall-web模块) 效果图 himall.g

  • spring-boot集成spring-security的oauth2实现github登录网站的示例

    spring-security 里自带了oauth2,正好YIIU里也用到了spring-security做权限部分,那为何不直接集成上第三方登录呢? 然后我开始了折腾 注意:本篇只折腾了spring-security oauth2的客户端部分,spring-security还可以搭建标准的oauth2服务端 引入依赖 <dependency> <groupId>org.springframework.security.oauth</groupId> <artif

  • 3行代码快速实现Spring Boot Oauth2服务功能

    这里的3行代码并不是指真的只需要写3行代码,而是基于我已经写好的一个Spring Boot Oauth2服务.仅仅需要修改3行数据库配置信息,即可得到一个Spring Boot Oauth2服务. 项目地址https://github.com/jeesun/oauthserver oauthserver 简介 oauthserver是一个基于Spring Boot Oauth2的完整的独立的Oauth服务器.仅仅需要创建相关数据表,修改数据库的连接信息,你就可以得到一个Oauth服务器. 支持的

  • springboot2.x实现oauth2授权码登陆的方法

    一 进行授权页 浏览器输入 http://localhost:8081/oauth/authorize?response_type=code&redirect_uri=http://localhost:8081/callback&client_id=android1&scop=all 二 使用资源站用户登陆 自动跨到资源登陆页,先登陆 三 授权资源类型 登陆成功后,去授权你的资源,这些资源是在AuthorizationServerConfig.configure方法里配置的 @Ov

  • 使用Springboot搭建OAuth2.0 Server的方法示例

    OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版. 本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749. OAuth 简介 OAuth 是由 Blaine Cook.Chris Messina.Larry Halff 及 David Recordon 共同发起的,目的在于为 API 访问授权提供一个安全.开放的标准. 基于 OAuth 认证授权具有以下特点: 安全.OAuth 与别的授

  • SpringBoot搭建多数据源的实现方法

    首先我们建立两个数据库(可以不在同一台电脑上): multiple_order: DROP DATABASE IF EXISTS `multiple_order`; CREATE DATABASE `multiple_order`; USE `multiple_order`; CREATE TABLE `order` ( `order_id` BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '订单id', `user_id` BIGINT U

  • Docker搭建Harbor公开仓库的方法示例

    上一篇博文讲到了Registry私有仓库,今天配置一下Harbor仓库,Harbor呢可以作为公开仓库,也可以作为私有仓库,今天就来配置一下Harbor如何实现公开仓库和私有仓库. 关于Registry公开仓库请访问博文:部署Docker私有仓库Registry Registry和Harbor的区别 Registry:是一个私有镜像仓库,图形化支持较差,小型企业使用: Harbor:支持可视化管理,支持私有仓库和公有仓库,支持镜像的管理控制: Docker Harbor的优点 VMWare公司的

  • Docker快速搭建Redis集群的方法示例

    什么是Redis集群 Redis集群是Redis提供的分布式数据库方案,集群通过分片(sharding)来进行数据共享,并提供复制和故障转移功能. 节点 一个Redis集群通常由多个节点(node)组成,在刚开始的时候,每个节点都是相互独立的,它们都处于一个只包含自己的集群当中,要组建一个真正可工作的集群,我们必须将各个独立的节点连接起来,构成一个包含多个节点的集群. 集群配置 配置文件 下载配置文件:https://raw.githubusercontent.com/antirez/redis

  • springboot搭建访客管理系统的实现示例

    项目介绍 springboot搭建的访客管理系统,针对高端基地做严格把控来访人员信息管理,用户后端可以设置多个管理员帐号,给予不同部门的管理层使用,用户管理可以增加/修改内部成员的基本信息,需要到访的人员必须通过进入程序,在访客预约里面提交预约申请,预约后管理员可查询预约记录以及访客出入记录. 项目适用人群 正在做毕设的学生,或者需要项目实战练习的Java学习者 开发环境 jdk 8 intellij idea tomcat 8.5.40 mysql 5.7 所用技术 springboot my

  • 使用springboot对linux进行操控的方法示例

    1,在pom中导入 <dependency> <groupId>ch.ethz.ganymed</groupId> <artifactId>ganymed-ssh2</artifactId> <version>build210</version> </dependency> 2,编写工具类 package org.jeecg.modules.system.util; /** * @Description: *

  • springboot返回html和jsp的方法示例

    一.返回html (1)添加maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> (2)thymeleaf模板默认寻找resources下,templates文件夹放html页面,static文件夹放css及js (3)引入

  • 运用springboot搭建并部署web项目的示例

    前言 一直以来都是用springmvc+mybatis进行后端接口开发工作,最近闲来无事,根据现有功能需求,用springboot+mybatis部署一套简单的web项目. 所用工具 IntelliJ IDEA 2018.1.4 JDK 1.8 apache-tomcat-8.0.50 所解决的问题 1.如何用idea创建springboot项目 2.如何进行 服务器.数据库.mybatis.视图解析器的配置 3.如何使用mybatis generator 自动生成代码 4.如何使用multip

  • 手把手带你搭建一个node cli的方法示例

    前言 前端日常开发中,会遇见各种各样的 cli,使用 vue 技术栈的你一定用过 @vue/cli ,同样使用 react 技术栈的人也一定知道 create-react-app .利用这些工具能够实现一行命令生成我们想要的代码模版,极大地方便了我们的日常开发,让计算机自己去干繁琐的工作,而我们,就可以节省出大量的时间用于学习.交流.开发. cli 工具的作用在于它能够将我们开发过程中经常需要重复做的事情利用一行代码来解决,比如我们在写需求的时候每新增一个页面就需要相应的增加该页面的初始化代码,

  • 使用Docker搭建ELK日志系统的方法示例

    以下安装都是以 ~/ 目录作为安装根目录. ElasticSearch 下载镜像: $ sudo docker pull elasticsearch:5.5.0 运行ElasticSearch容器: $ sudo docker run -it -d -p 9200:9200 -p 9300:9300 \ -v ~/elasticsearch/data:/usr/share/elasticsearch/data \ --name myes elasticsearch:5.5.0 特别注意的是如果使

随机推荐