IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 第15章 Spring Security OAuth2 初始 -> 正文阅读

[Java知识库]第15章 Spring Security OAuth2 初始

之前在学习 Spring Security 就对第三方登录比较感兴趣,但是一直没有去研究,最近因为业务需求需要去集成 Google 登录,便开始研究,从开始一头雾水,到现在算是清楚了 OAuth2 Login 的认证授权流程。我会从如何去使用、源码解析角度给大家分享,也会分享一些开发中遇到一些坑。

1.申请Google API和服务

首先我们需要到 Google Developers Console 开发者控制台去申请。然后,需要创建一个 Project,找到 API和服务,最后去创建 OAuth 同意屏幕 和 凭据。需要注意的是,重定向URI设置,我们需要在后续Spring Boot中application.yml 使用到,还需要在 Spring Security Config 配置类去配置。


2.Google OAuth2 Login 认证授权流程

一开始不知道这背后的原理是什么,为什么几行代码集成第三方登录。其实这里就是接口来获取Google 用户信息。这里梳理了Google OAuth2 Login 认证授权的时序图,可以更好帮助我们理解其背后原理。
在这里插入图片描述

3.Maven依赖

<dependency>
 <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

4.application.yml配置

logging:
  level:
    org.springframework: DEBUG


spring:
  thymeleaf:
    cache: false
    prefix: classpath:/templates/
    encoding: UTF-8 #??
    suffix: .html #????
    mode: HTML #??
  security:
    oauth2:
      client:
        registration:
          google:
            clientId: 你的clientId
            clientSecret: 你的clientSecret
            redirectUri: http://localhost:8080/oauth2/code/google
            scope:
              - email
              - profile
server:
  port: 8080

5.SecurityConfig 配置类

@Configuration
@EnableWebFluxSecurity
@Slf4j
public class SecurityConfig {

    @Autowired
    private ReactiveClientRegistrationRepository clientRegistrationRepository;

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        return http.csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint(new RedirectServerAuthenticationEntryPoint("/auth/login"))
                .and()
                .authorizeExchange(authorizeExchangeSpec -> authorizeExchangeSpec
                        .pathMatchers("/auth/**", "/oauth2/**").permitAll()
                        .anyExchange()
                        .authenticated())
                .oauth2Login(oauth2Login -> oauth2Login
                        // 发起 OAuth2 登录的地址(服务端)
                        .authorizationRequestResolver(new DefaultServerOAuth2AuthorizationRequestResolver(
                                clientRegistrationRepository,
                                new PathPatternParserServerWebExchangeMatcher(
                                        "/oauth2/authorization/{registrationId}")))
                        // OAuth2 外部用户登录授权后的跳转地址(服务端)
                        .authenticationMatcher(new PathPatternParserServerWebExchangeMatcher(
                                "/oauth2/code/{registrationId}"))
                        // OAuth2 登录成功后
                        .authenticationSuccessHandler(new OAuth2AuthenticationSuccessHandler())
                        // OAuth2 登录失败后
                        .authenticationFailureHandler(new OAuth2AuthenticationFailureHandler()))
                .build();
    }
}

6.登录页面

在登录页面,会有 Login With Google 登录链接,这是发起Google OAuth2 Login 授权的入口。

<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
  <h2>Please Login</h2>
  <br/>
</div>
<div>
  <h4><a th:href="@{/oauth2/authorization/google}">Login with Google</a></h4>
</div>
<div><p>OR</p></div>

<form th:action="@{/login}" method="post" style="max-width: 400px; margin: 0 auto;">
  <div class="border border-secondary rounded p-3">
    <div th:if="${param.error}">
      <p class="text-danger">Invalid username or password.</p>
    </div>
    <div th:if="${param.logout}">
      <p class="text-warning">You have been logged out.</p>
    </div>
    <div>
      <p><input type="email" name="email" required class="form-control" placeholder="E-mail" /></p>
    </div>
    <div>
      <p><input type="password" name="pass" required class="form-control" placeholder="Password" /></p>
    </div>
    <div>
      <p><input type="submit" value="Login" class="btn btn-primary" /></p>
    </div>
  </div>
</form>
</body>
</html>

7.授权成功回调

当认证授权成功后,我们会让请求重定向到 /user/info/1 接口。

@Slf4j
public class OAuth2AuthenticationSuccessHandler implements ServerAuthenticationSuccessHandler {

    private ServerRedirectStrategy redirectStrategy = new DefaultServerRedirectStrategy();

    @SneakyThrows
    @Override
    public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
        log.info("oauth2 authentication success");
        return Mono.empty().then(redirectStrategy.sendRedirect(webFilterExchange.getExchange(), new URI("/user/info/1")));
    }
}

8.授权失败回调

当认证授权失败后,我们会让请求重定向到 /auth/login 登录接口。

@Slf4j
public class OAuth2AuthenticationSuccessHandler implements ServerAuthenticationSuccessHandler {

    private ServerRedirectStrategy redirectStrategy = new DefaultServerRedirectStrategy();

    @SneakyThrows
    @Override
    public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
        log.info("oauth2 authentication success");
        return Mono.empty().then(redirectStrategy.sendRedirect(webFilterExchange.getExchange(), new URI("/user/info/1")));
    }
}

9.测试

首先,去访问 /user/info/1 接口,如果没有登录过会被重定向到登录页面。点击 Google 登录按钮,开始 Google OAuth2 Login 授权流程。成功后,会重定向到 /user/info/1 接口。注意:在测试时,首先要确保你可以访问 Google,如果你是在本地运行代码还要确保你的代码也能访问Google。本地调试可以安装 Proxifier
在这里插入图片描述

在这里插入图片描述

到此,功能已经基本实现,但是有点小缺陷。你可能会发现,当它运行在一台机器上是好好的,但是运行在两个机器上,就会报错了。为什么呢?原因是:默认是用 WebSession 存储 授权信息。解决办法有几种:

  • Nginx 可以设置 会话粘性
  • 自定义使用 Cookie 存储 授权信息
  • 使用分布式Session

更多信息

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-05 23:25:27  更:2022-07-05 23:26:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 15:17:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码