当前位置: 首页 > news >正文

Spring Security 集成 OIDC 项目编码 | 认证(三)

在上一篇文章《OIDC 在 Authing 控制台的配置流程 | 认证(二)》中,我们讲述了如何在 Authing 平台配置项目集成中需要的 OIDC 的配置,以及在后期开发过程中如何获取配置。同时,也提前让大家预习和熟悉了一些项目搭建和编码过程中需要的知识点。

接下来这一小节,就让我们一起来完成项目搭建和编码过程吧。

01

项目搭建

使用 Spring Initializr 快速构建项目

打开 IDEA,点击 New Project 创建一个新项目,选择 Spring Initializr 创建一个 Spring Boot 项目,输入项目的 Group 以及 Artifact 信息。

添加 Spring Web, Spring Security 依赖。

另外,集成过程中需要在 pom.xml 中添加一些其他的依赖包,如下:

<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<!--远程调用接口使用-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.11</version>
</dependency>

使用 maven 工具构建项目

打开 IDEA,点击 New Project 创建一个新项目,选择 maven 创建一个 maven 项目,然后点击 Next,填写项目名称,最后 Finish 即可。

接下来在 pom.xml 中添加父工程依赖和集成过程中需要的其它依赖包。

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

    <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.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
        </dependency>
        <!--远程调用接口使用-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.11</version>
        </dependency>

说明:其中,hutool-all 工具包的作用是远程调用接口,当收到回调请求时,会使用该工具包远程调用 Authing 接口,即通过 code 换取 token 的流程,后续自动回调接口编码会使用到。

🎉🎉🎉至此,你已经完成了使用 Spring Initializr 和 maven 两种方式构建项目,请选择一种适合自己项目开发的方式即可。

02

项目编码

测试项目

创建好项目后,在 IDEA 中运行项目,使用浏览器访问 http://localhost:8080 会自动跳转到 /login 路由,可以看到页面上出现了一个基础的登录表单,说明项目初始化成功。

配置项目中的配置文件

找到:
src/main/resources/application.properties,将其重命名为 application.yml,并添加如下内容。

spring:
  security:
    oauth2:
      client:
        registration:
          authing:
            client-id: {替换为你的App ID如:App Secret5e72d72e3798fb03e1d57b13}
            client-secret: {替换为你的App Secret如:931f19ce2161e5560c072f586c706ee6}
            redirect-uri: {替换为登录的回调地址}
            client-authentication-method: post
            authorization-grant-type: authorization_code
            scope:
              - openid
              - profile
        provider:
          authing:
            issuer-uri: https://{替换为你的Issuer,如:authing-net-sdk-demo}.authing.cn/oidc
            user-name-attribute: preferred_username

需要将这里的 {client_id}、{secret_secret}、{issuer-uri} 、{redirect-uri} 替换成 《认证(二)》 中应用配置中的实际信息。

自动回调接口编码

在项目下新建一个 package(package cn.authing.springsecurityoidc.controller),然后新建一个 CallBackController,此接口作用是通过 Authing OIDC 的 code 获取 token 的过程。注意,下面的参数都是 OIDC 的标准,不能乱改,这也是标准协议的规定,参数名所对应的值也就是之前在 Authing 平台应用所配置的那些。

package cn.authing.springsecurityoidc.controller;

import cn.hutool.http.HttpUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class CallBackController {

    @GetMapping("/callback")
    public String getTokenByCode(String code){
        //'https://<你的应用域名>.authing.cn/oidc/token
//        --data-urlencode 'code=61yhuOVrgyhKlFTU~bnEKA_fnnz' \
//        --data-urlencode 'client_id=5e37979f7b757ead14c534af' \
//        --data-urlencode 'client_secret=64b517f8de3648091654eb4ee9b479d3' \
//        --data-urlencode 'grant_type=authorization_code' \
//        --data-urlencode 'redirect_uri=https://baidu.com'

        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("code",code);
        paramMap.put("client_id","61319680ea8b30c9ca9ca071");
        paramMap.put("client_secret","cc8a53d7e22ce6b845330ced6cc5d9f2");
        paramMap.put("grant_type","authorization_code");
        paramMap.put("redirect_uri","http://localhost:8080/callback");
        String result = HttpUtil.post("https://cjtjls-demo.authing.cn/oidc/token", paramMap);
        return result;
    }
}

添加配置文件类

在项目下新建一个 package(cn.authing.springsecurityoidc.config),然后新建一个SpringSecurityConfig,Spring Security 默认拦截所有的接口,此配置类是为了放行我们自己需要开放的接口。

package cn.authing.springsecurityoidc.config;

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;

import static org.springframework.security.config.Customizer.withDefaults;

@EnableWebSecurity(debug = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin().disable();
        http.csrf().and().cors().disable();
        http.authorizeRequests()
                .mvcMatchers("callback","")
                .permitAll()
                .anyRequest().authenticated();
        // 授权码模式回调
         http.oauth2Login(withDefaults());
    }
}

运行项目

一切准备就绪了,现在启动项目并访问 http://localhost:8080,即可看到 Authing 登录窗口。

Spring Security 默认会保护首页,在访问首页时会进行认证,未认证的访问请求会跳转到 /login。注册并登录后,会跳转回首页,此时可以看到页面上的欢迎语显示了当前登录用户的用户名。

当登录成功后,会自动回调到我们之前自己编码的接口,即前面所概述的 Code 换取 Token 的过程。此时界面会拿到返回值,如下:

{
        "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InhENWlTYVJiU0dZQzFmdWFTRVdQXy1hejBORW5qSmtoZG00bTJ3X3ZwMHcifQ.eyJqdGkiOiJnbHdLbmMzbzlXYlVLUE5pWUF1V00iLCJzdWIiOiI2MTRmZDlhZTQyYjE5MmZjMzI4MjNiMTAiLCJpYXQiOjE2MzU5MjQwNjgsImV4cCI6MTYzNzEzMzY2OCwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSIsImlzcyI6Imh0dHBzOi8vY2p0amxzLWRlbW8uYXV0aGluZy5jbi9vaWRjIiwiYXVkIjoiNjEzMTk2ODBlYThiMzBjOWNhOWNhMDcxIn0.KG6_SCaXfm082WAuPZu2-gR2cuA1Heg50EeVF1ldAO_fvb72pkmgs7EiWXjLJwYUj3CNejIS1GwcDy9gVWw8jfO-aRxUyRMplDY-axzgu5frCxYrg_K7LhlU1xvQJIMKTx7HY7rldbbAX0JzqJx-xHCJItUiggvHjvF9-B1twmMP7Ua-UQxQdgkFd1SmbN9LwqxCo8AzsbX6jcBNJ3Ughv0_jUxYp6QPAeIEkXmOYlwdJR-4Rdn9XxPya5yF4wxgwZ_oybjViESr7BDwEXEPVWTF6czGzctmfhCD7EEE4sLWaP6TSmXAHyCYp6TVNpVNAXg2sKQSfbwPdR8PxOhFmg",
        "expires_in": 1209600,
        "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InhENWlTYVJiU0dZQzFmdWFTRVdQXy1hejBORW5qSmtoZG00bTJ3X3ZwMHcifQ.eyJzdWIiOiI2MTRmZDlhZTQyYjE5MmZjMzI4MjNiMTAiLCJiaXJ0aGRhdGUiOm51bGwsImZhbWlseV9uYW1lIjpudWxsLCJnZW5kZXIiOiJVIiwiZ2l2ZW5fbmFtZSI6bnVsbCwibG9jYWxlIjpudWxsLCJtaWRkbGVfbmFtZSI6bnVsbCwibmFtZSI6bnVsbCwibmlja25hbWUiOm51bGwsInBpY3R1cmUiOiJodHRwczovL2ZpbGVzLmF1dGhpbmcuY28vYXV0aGluZy1jb25zb2xlL2RlZmF1bHQtdXNlci1hdmF0YXIucG5nIiwicHJlZmVycmVkX3VzZXJuYW1lIjpudWxsLCJwcm9maWxlIjpudWxsLCJ1cGRhdGVkX2F0IjoiMjAyMS0xMS0wMVQxMToyOToyMi4zMDlaIiwid2Vic2l0ZSI6bnVsbCwiem9uZWluZm8iOm51bGwsIm5vbmNlIjoiekx6WndwR05faEpDdDNRTVlvMk12TmplT2o4aTM0U0tpR3ZlMVc0d2R1ayIsImF0X2hhc2giOiJFcGZUR1M2dFNpVnhiMkdPbkxUazNRIiwiYXVkIjoiNjEzMTk2ODBlYThiMzBjOWNhOWNhMDcxIiwiZXhwIjoxNjM3MTMzNjY4LCJpYXQiOjE2MzU5MjQwNjgsImlzcyI6Imh0dHBzOi8vY2p0amxzLWRlbW8uYXV0aGluZy5jbi9vaWRjIn0.iRoYa0JLoBJPXAPD8LjHnuvjQsQ5o5g9qUjPAj1aTMbZqa9GI3gUfxW-smudKJCJmGfYDYJaRP8_szdS03cXCt8u4rGc7y6e6y2Fqq1pssz3VlpRm9t_7LxJrUeBFu1ef87KWO0WZg5Nd6mdoIEAJXwRSW8BbTE_ARg8DZiOcrk3YJ2PxFqb6Tepf3Vw6XyxkHjOfDgJNDnnwHsiMGdXzTMYJwMNKkEjP8xQJl9oh9nOSDF_33-4Btn3nuQQPZ6ndTEcPbaYOo6PN_0IaisjuE3rzyCdGNXxgPrbXg2qywMKZrtj-AKROZ43IA2ito_MtJ6292N6IlFv9SR0Gr4hpw",
        "scope": "openid profile",
        "token_type": "Bearer"
}

项目地址
https://github.com/Authing/example-spring-boot-oidc

恭喜 🎉,到此你已经学会了 Spring Security 5 集成 Authing OIDC 认证授权的整个流程。后续还有更多的干货,持续关注吧!

文章回顾:

《Spring Security 集成 Authing OIDC | 认证(一)》

《OIDC 在 Authing 控制台的配置流程 | 认证(二)》

《开发者谈 | OAuth 2.0 和 OIDC 协议的关系?(内含必看案例)》

相关文章:

  • 漏电继电器HLJ-400FS
  • HTB-Explore
  • DoozyUI⭐️十三 、UIToggle:开关讲解
  • windows部署nginx
  • 需求变化频繁的情况下,如何实施自动化测试
  • Compose和AndroidView的交互
  • java计算机毕业设计社区物品交易系统源码+系统+数据库+lw文档+mybatis+运行部署
  • Spring AOP快速入门----XML方式和注解方式
  • 读源码学算法之Octree color quantization
  • C#调用C++生成的DLL 找不到入口点 以及 尝试读取或写入受保护的内存
  • 品牌是选择KOC还是KOL?抖音KOC如何进行推广投放?
  • css同时设置最大宽度和最小宽度
  • 微信小程序播放视频的时候如果突然插入一个音频视频就会卡顿一下
  • S7协议下,如何搭建触摸屏与PLC之间无线通信?
  • java SpringBoot 静态方法中获取@Value注入的值
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • gops —— Go 程序诊断分析工具
  • HashMap ConcurrentHashMap
  • js数组之filter
  • Laravel Mix运行时关于es2015报错解决方案
  • Logstash 参考指南(目录)
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • Python十分钟制作属于你自己的个性logo
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 利用jquery编写加法运算验证码
  • 实现菜单下拉伸展折叠效果demo
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 微信公众号开发小记——5.python微信红包
  • 硬币翻转问题,区间操作
  • 追踪解析 FutureTask 源码
  • FaaS 的简单实践
  • hi-nginx-1.3.4编译安装
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • ​低代码平台的核心价值与优势
  • #define用法
  • #stm32驱动外设模块总结w5500模块
  • $L^p$ 调和函数恒为零
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (70min)字节暑假实习二面(已挂)
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (分布式缓存)Redis持久化
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)visual stdio 书签功能介绍
  • (转)关于多人操作数据的处理策略
  • (转载)利用webkit抓取动态网页和链接
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)