ASP.NET Core SignalR身份验证
在需要登录才能访问的集线器类上或者方法上添加[Authorize]。也支持角色等设置,可以设置到Hub或者方法上。
配置好User、Role、MyDbContext、JWTSettings、IdentityHelper
Program.cs
using SignaIR的基本使用;
using Scalar.AspNetCore;
using Identity框架;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using System.Text;var builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers();
builder.Services.AddOpenApi();//添加数据库上下文
builder.Services.AddDbContext<MyDbContext>(opt =>
{string connStr = Environment.GetEnvironmentVariable("ConnStr");opt.UseSqlServer(connStr);
});//添加Identity服务
builder.Services.AddDataProtection();
builder.Services.AddIdentityCore<MyUser>(options =>
{//设置密码规则,不需要数字,小写字母,大写字母,特殊字符,长度为6options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds(30);options.Password.RequireDigit = false;options.Password.RequireLowercase = false;options.Password.RequireUppercase = false;options.Password.RequireNonAlphanumeric = false;options.Password.RequiredLength = 6;options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;
});
var idBuilder = new IdentityBuilder(typeof(MyUser), typeof(MyRole), builder.Services);
idBuilder.AddEntityFrameworkStores<MyDbContext>().AddDefaultTokenProviders().AddRoleManager<RoleManager<MyRole>>().AddUserManager<UserManager<MyUser>>();//添加JWT设置
builder.Services.Configure<JWTSettings>(builder.Configuration.GetSection("JWT"));
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>
{var jwtOpt = builder.Configuration.GetSection("JWT").Get<JWTSettings>();byte[] key = Encoding.UTF8.GetBytes(jwtOpt.SecKey);//设置对称秘钥var secKey = new SymmetricSecurityKey(key);//设置验证参数opt.TokenValidationParameters = new(){ValidateIssuer = false,//是否验证颁发者ValidateAudience = false,//是否验证订阅者ValidateLifetime = true,//是否验证生命周期ValidateIssuerSigningKey = true,//是否验证签名IssuerSigningKey = secKey//签名秘钥};//设置事件opt.Events = new JwtBearerEvents{OnMessageReceived = context =>{//WebSocket不支持自定义报文头,所以把JWT通过url中的QueryString传递var accessToken = context.Request.Query["access_token"];var path = context.HttpContext.Request.Path;//如果是MyHub的请求,就在服务器端的OnMessageReceived中把QueryString中的JWT读出来赋值给context.Tokenif (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/MyHub"))){context.Token = accessToken;}return Task.CompletedTask;}};});
//SignalR
builder.Services.AddSignalR();
//跨域
string[] urls = new[] { "http://localhost:5173" };
builder.Services.AddCors(options =>options.AddDefaultPolicy(builder => builder.WithOrigins(urls).AllowAnyMethod().AllowAnyHeader().AllowCredentials()));var app = builder.Build();if (app.Environment.IsDevelopment())
{app.MapOpenApi();app.MapScalarApiReference();
}
app.UseCors();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapHub<MyHub>("/MyHub");
app.MapControllers();app.Run();
MyHub.cs
[Authorize]
public class MyHub : Hub
{public Task SendPublicMessage(string message){var claim = this.Context.User.FindFirst(ClaimTypes.Name);string connId = this.Context.ConnectionId;string msgToSend = $"{connId}{DateTime.Now}:{message}{claim.Value}";return Clients.All.SendAsync("ReceivePublicMessage", msgToSend);}
}
DemoController.cs
[Route("api/[controller]/[action]")]
[ApiController]
public class DemoController : ControllerBase
{private readonly UserManager<MyUser> userManager;private readonly IOptionsSnapshot<JWTSettings> jwtSettingsOpt;public DemoController(UserManager<MyUser> userManager, IOptionsSnapshot<JWTSettings> jwtSettingsOpt){this.userManager = userManager;this.jwtSettingsOpt = jwtSettingsOpt;}[HttpPost]public async Task<ActionResult<string>> Login(LoginRequest req){//根据用户名查找用户var user = await userManager.FindByNameAsync(req.UserName);if (user == null){return BadRequest("用户或密码错误1");}//判断是否登录成功,失败则记录失败次数if (await userManager.CheckPasswordAsync(user, req.Password)){//登录成功,重置失败次数,CheckAsync判断操作是否成功,失败则抛出异常await userManager.ResetAccessFailedCountAsync(user).CheckAsync();await userManager.UpdateAsync(user);//身份验证声明List<Claim> claims = new List<Claim>{new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),new Claim(ClaimTypes.Name, user.UserName),};//获取用户角色,添加到声明中var roles = await userManager.GetRolesAsync(user);foreach (var role in roles){claims.Add(new Claim(ClaimTypes.Role, role));}//生成JWTstring key = jwtSettingsOpt.Value.SecKey;DateTime expires = DateTime.Now.AddSeconds(jwtSettingsOpt.Value.ExpireSeconds);byte[] keyBytes = Encoding.UTF8.GetBytes(key);var secKey = new SymmetricSecurityKey(keyBytes);var credentials = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256Signature);var tokenDescriptor = new JwtSecurityToken(claims: claims,//声明expires: expires,//过期时间signingCredentials: credentials//签名凭据);string jwt = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);return jwt;}else{await userManager.AccessFailedAsync(user).CheckAsync();return BadRequest("用户或密码错误2");}}
}
Vue
<template><input type="text" v-model="state.userMessage" v-on:keypress="txtMsgOnkeypress" /><div>用户名<input type="text" v-model="state.loginData.username" />密码<input type="password" v-model="state.loginData.password" /><button v-on:click="loginClick">登录</button></div><div><ul><li v-for="(msg, index) in state.messages" :key="index">{{ msg }}</li></ul></div>
</template><script>
import { reactive } from 'vue';
import * as signalR from '@microsoft/signalr';
import axios from 'axios';let connection;
export default {name: 'Login',setup() {//创建响应式对象const state = reactive({accessToken: "", userMessage: "", messages: [],loginData: { userName: "", password: "" }});//SignalR连接const startConn = async function () {const transport = signalR.HttpTransportType.WebSockets;const options = { skipNegotiation: true, transport: transport };options.accessTokenFactory = () => state.accessToken;connection = new signalR.HubConnectionBuilder().withUrl('https://localhost:7181/MyHub', options).withAutomaticReconnect().build();try {await connection.start();} catch (err) {alert(err);return;}//注册ReceivePublicMessage事件,接收消息,添加到messages数组connection.on('ReceivePublicMessage', msg => {//监听服务器端发送过来的信息state.messages.push(msg);});}//点击登录const loginClick = async function () {const resp = await axios.post('https://localhost:7181/api/Demo/Login', state.loginData).then((response) => {state.accessToken = response.data;startConn()})};//按下回车键发送消息,调用SendPublicMessage方法,发送消息,清空输入框const txtMsgOnkeypress = async function (e) {if (e.keyCode != 13) return;await connection.invoke("SendPublicMessage", state.userMessage); state.userMessage = "";};//返回响应式对象和方法return { state, txtMsgOnkeypress, loginClick };},
}
</script>
相关文章:
ASP.NET Core SignalR身份验证
在需要登录才能访问的集线器类上或者方法上添加[Authorize]。也支持角色等设置,可以设置到Hub或者方法上。 配置好User、Role、MyDbContext、JWTSettings、IdentityHelper Program.cs using SignaIR的基本使用; using Scalar.AspNetCore; using Identity框架; us…...
查询语句来提取 detail 字段中包含 xxx 的 URL 里的 commodity/ 后面的数字串
您可以使用以下 SQL 查询语句来提取 detail 字段中包含 oss.kxlist.com 的 URL 里的 commodity/ 后面的数字串: <p><img style"max-width:100%;" src"https://oss.kxlist.com//8a989a0c55e4a7900155e7fd7971000b/commodity/20170925/20170…...
linux本地部署deepseek
目录 安装ollama安装open-webui网页客户端界面本地安装open-webui直接安装在裸机上安装在docker中 外部服务器安装open-webui,并链接本地的ollama服务直接安装在外部服务器裸机上配置systemd启动open-webui 安装在docker中 最后更新时间2024-05-24 安装ollama olla…...
ESP32_H2(IDF)学习系列-蓝牙基础学习(上)
一、简介 参考:[乐鑫-蓝牙] Bluetooth LE 的分层架构 Bluetooth LE 协议定义了三层软件结构,自上而下分别是 应用层 (Application Layer) 应用层(Application Layer) 主机层 (Host Layer) 控制器层 (Controller Layer) 应用…...
防御综合实验
需求一 配置vlan [SW2]int g 0/0/2 [SW2-GigabitEthernet0/0/2]port link-type access [SW2-GigabitEthernet0/0/2]port default vlan 10 [SW2-GigabitEthernet0/0/2]int g0/0/3 [SW2-GigabitEthernet0/0/3]port link-type access [SW2-GigabitEthernet0/0/3]port default vl…...
Blazor-<select>
今天我们来说说<select>标签的用法,我们还是从一个示例代码开始 page "/demoPage" rendermode InteractiveAuto inject ILogger<InjectPage> logger; <h3>demoPage</h3> <select multiple>foreach (var item in list){<…...
zy.21
PHP(续) PHP代码执行漏洞 1.PHP中代码漏洞的概念 代码执行漏洞就是在代码中若存在eval、assert等能将所接收的参数作为代码去执行,并且拼接的内容可被访问者控制,也就是把传入的参数给拼接进去了,造成了额外的代码执行,也就造成了代码执行漏洞。(大概原理&#x…...
【c++】四种类型转换形式
【c】四种类型转换形式 编译时: static_cast(静态转换) const_cast(去常性转换) reinterpret_cast(重新解释转换,直接转换地址) 运行时: dynamic_cast(动态转换,运行时类…...
在npm上传属于自己的包
最近在整理代码,上传到npm方便使用,所以学习了如何在npm发布一个包,整理写成一篇文章和大家一起交流。 1、注册npm账号 npm | Home 2、确保是登录状态 (在包目录下,终端执行 npm login) 按enter键自动打开页面&…...
关系型数据库主备高可用方案对比笔记
目录标题 数据库高可用性解决方案对比Oracle Data GuardMySQL 主从复制SQL Server AlwaysOnPG Patroni 流复制达梦 DMDataWatch人大金仓 repmgr 备库故障是否影响主库?表格关系型数据库主备高可用方案对比笔记 数据库高可用性解决方案对比 Oracle Data Guard Orac…...
怎么查看电脑显存大小(查看电脑配置)
这里提供一个简单的方法查看 winr打开cmd 终端输入dxdiag进入DirectX 点击显示查看设备的显示内存(VRAM) 用这个方法查看电脑配置和显存是比较方便的 dxdiag功能 Dxdiag是Windows的DirectX诊断工具,其主要作用包括但不限于以下几点&#…...
深入理解指针(二)
深入理解指针(二) 前言:一、const修饰指针1.const修饰变量2.const修饰的指针变量 二、野指针1.野指针的成因(1).指针的未初始化(2).指针的越界访问(3).指针的空间释放 2.如何规避野指针(1).指针初始化(2).小心访问越界(3)指针不再使用的时候&…...
非华为电脑制作一碰传NFC贴纸
前提: 在笔记本上安装好华为电脑管家,可以在 github 上下载,并测试可以正常和手机或平板连接步骤: 1、打开电脑华为电脑管家,点【快捷服务】,记录下序列号,一般安装后会生成16位的序列号 2、…...
Wpf美化按钮,输入框,下拉框,dataGrid
Wpf美化按钮,输入框,下拉框,dataGrid 引用代码后 引用资源 <ControlTemplate x:Key"CustomProgressBarTemplate" TargetType"ProgressBar"><Grid><Border x:Name"PART_Track" CornerRadius&q…...
Office/WPS接入DeepSeek等多个AI工具,开启办公新模式!
在现代职场中,Office办公套件已成为工作和学习的必备工具,其功能强大但复杂,熟练掌握需要系统的学习。为了简化操作,使每个人都能轻松使用各种功能,市场上涌现出各类办公插件。这些插件不仅提升了用户体验,…...
【深度学习】多目标融合算法(四):多门混合专家网络MMOE(Multi-gate Mixture-of-Experts)
目录 一、引言 二、MMoE(Multi-gate Mixture-of-Experts,多门混合专家网络) 2.1 技术原理 2.2 技术优缺点 2.3 业务代码实践 2.3.1 业务场景与建模 2.3.2 模型代码实现 2.3.3 模型训练与推理测试 2.3.4 打印模型结构 三、总结 一、…...
git submodule使用
git submodule 用于关联其他独立的仓库。 它有着几点好处: 代码复用:可以将工具代码放到单独的仓库,再通过 submodule 关联。模块化开发:可以将项目拆分成多个模块,每个模块设置单独仓库独立开发,再通过 su…...
朝天椒USB服务器:解决加密狗远程连接
本文探讨朝天椒USB服务器用Usb Over Network技术,解决加密狗在虚拟机、云主机甚至异地的远程连接问题。 在企业数字化转型的浪潮中,加密狗作为防止软件盗版的重要手段,广泛应用于各类软件授权场景。然而,随着企业超融合进程不断加…...
[笔记.AI]deepseek-r1的不同版本(满血版、蒸馏版、量化)
满血版:是原始的高性能模型; 蒸馏版(Distill):是指将大型模型(教师模型)的知识转移到较小的模型(学生模型)中,以保持性能的同时减少计算资源的需求࿱…...
Kokoro 开源文本转语音引擎上线!多语言支持,无需联网,浏览器内极速运行
Kokoro 是一款轻量级的开源文本转语音(TTS)引擎,凭借其高效能和轻量化设计,迅速在技术社区中引起关注。本文将详细介绍 Kokoro 的主要特点,并提供在浏览器和 Python 环境中的代码示例,帮助您快速上手。 1. Kokoro:可在浏览器中运行的 TTS 引擎 1.1 简介 Kokoro 是一个…...
Unity 基础编程
在这个练习中将新建unity脚本,控制player的运动与转动,实现用代码检测碰撞与删除物体。 该练习将应用附件中的项目文件,该文件与Unity快速练习的文件是同一个项目文件。 一、构建Player运动脚本 该部分将构建一个在场景中由玩家控制游戏物…...
CTFHub-RCE系列wp
目录标题 引言什么是RCE漏洞 eval执行文件包含文件包含php://input读取源代码远程包含 命令注入无过滤过滤cat过滤空格过滤目录分隔符过滤运算符综合过滤练习 引言 题目共有如下类型 什么是RCE漏洞 RCE漏洞,全称是Remote Code Execution漏洞,翻译成中文…...
基于YoloV11和驱动级鼠标模拟实现Ai自瞄
本文将围绕基于 YoloV11 和驱动级鼠标实现 FPS 游戏 AI 自瞄展开阐述。 需要着重强调的是,本文内容仅用于学术研究和技术学习目的。严禁任何个人或组织将文中所提及的技术、方法及思路应用于违法行为,包括但不限于在各类游戏中实施作弊等违规操作。若因违…...
基于微信小程序的博物馆预约系统的设计与实现
hello hello~ ,这里是 code袁~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 🦁作者简介:一名喜欢分享和记录学习的在校大学生…...
R语言LCMM多维度潜在类别模型流行病学研究:LCA、MM方法分析纵向数据
全文代码数据:https://tecdat.cn/?p39710 在数据分析领域,当我们面对一组数据时,通常会有已知的分组情况,比如不同的治疗组、性别组或种族组等(点击文末“阅读原文”获取完整代码数据)。 然而,…...
python卷积神经网络人脸识别示例实现详解
目录 一、准备 1)使用pytorch 2)安装pytorch 3)准备训练和测试资源 二、卷积神经网络的基本结构 三、代码实现 1)导入库 2)数据预处理 3)加载数据 4)构建一个卷积神经网络 5࿰…...
如何把邮件批量导出到本地
最近遇到邮箱满了的问题,需要把邮件批量导出到本地,然后清空邮箱。 问题是这个邮箱的官网,没有批量导出按钮,比较麻烦;总不能一封一封下载到本地,上万的。 找到了一个好用的工具,Mozilla Thun…...
C++智能指针的使用
文章目录 智能指针的使用和原理智能指针的使用场景RAII和智能指针C标准库智能指针的使用 智能指针的使用和原理 智能指针的使用场景 1. 下面的程序中,new了以后,我们也delete了,但是因为抛异常导致后面的delete没有得到执行,所以…...
Docker安装Redis
一、保证Docker提起来了 systemctl status docker想这没有启动要先启动一下 systemctl status docke二、拉取Redis(默认拉最新版) sudo docker pull redis检查一下拉成功没有 docker images三、创建相关目录 mkdir -p /home/redis/{conf,data}四、…...
深入理解MySQL索引底层数据结构
文章目录 前言一、MySQL索引是什么?二、索引的核心需求三、MySQL为什么选择BTree做为数据结构1.如果使用的是Hash 做为数据结构2.如果使用二叉树做为数据结构3.使用红黑树做为数据结构4.使用B-Tree做为数据结构5.BTree做为数据结构 4.BTree深度剖析结构特性与 B-Tre…...
udp和tcp的区别
目录 UDP 和 TCP 的区别 1. 连接性 2. 可靠性 3. 数据传输顺序 4. 流量控制和拥塞控制 5. 效率 6. 应用场景 UDP 和 TCP 的 C/C 代码实现区别 1. TCP 服务器端和客户端 TCP 服务器端(Server) TCP 客户端(Client) 2. U…...
VMware 虚拟机 ubuntu 20.04 扩容工作硬盘
一、关闭虚拟机 关闭虚拟机参考下图,在vmware 调整磁盘容量 二、借助工具fdisk testubuntu ~ $ df -h Filesystem Size Used Avail Use% Mounted on udev 1.9G 0 1.9G 0% /dev tmpfs 388M 3.1M 385M 1% /run /dev/sda5 …...
MapReduce是什么?
MapReduce 是一种编程模型,最初由 Google 提出,旨在处理大规模数据集。它是分布式计算的一个重要概念,通常用于处理海量数据并进行并行计算。MapReduce的基本思想是将计算任务分解为两个阶段:Map 阶段和 Reduce 阶段。 Map 阶段&a…...
跨越边界,大模型如何助推科技与社会的完美结合?
点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 概述 2024年,大模型技术已成为人工智能领域的焦点。这不仅仅是一项技术进步,更是一次可能深刻影响社会发展方方面面的变革。大模型的交叉能否推动技术与社会的真正融合?2025年…...
计算机毕业设计SpringBoot校园二手交易小程序 校园二手交易平台(websocket消息推送+云存储+双端+数据统计)(源码+文档+运行视频+讲解视频)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
RK3568平台开发系列讲解(ConfigFS篇)ConfigFS核心数据结构
🚀返回专栏总目录 文章目录 一、数据结构二、结构体关系三、案例3.1、configfs_subsystem 实例3.2、config_group 实例化四、属性和方法五、config_item实例化沉淀、分享、成长,让自己和他人都能有所收获!😄 理解 ConfigFS 的核心数据结构对于深入使用和定制 ConfigFS 非…...
【04】RUST特性
文章目录 隐藏shadowing所有权ownership堆区&栈区所有权规则变量&数据Copy Trait与Drop TraitCopy TraitDrop Trait移动克隆函数参数与返回值的所有权参数引用可变引用悬垂引用slice生命周期隐藏shadowing 有点像同名覆盖 let mut guess = String::new();let guess: u3…...
c语言函数学习
C语言函数学习笔记:从入门到实践 一、什么是函数? 函数是C语言中用于封装特定功能的代码块,是模块化编程的核心。通过函数可以实现: 代码复用:避免重复编写相同逻辑 逻辑清晰:将复杂程序分解为多个小模块…...
LSTM的介绍
网上一些描述LSTM文章看的云里雾里,只是介绍LSTM 的结构,并没有说明原理。我这里用通俗易懂的话来描述一下。 我们先来复习一些RNN的核心公式: h t t a n h ( W h h t − 1 W x x t b h ) h_t tanh(W_h h_{t-1} W_x x_t b_h) httan…...
XML DOM
XML DOM XML DOM(Document Object Model)是一种用于访问和操作XML文档的标准方式。它提供了一种树形结构来表示XML文档,使得开发者能够方便地对XML数据进行读取、修改和操作。本文将详细介绍XML DOM的基本概念、结构、操作方法以及应用场景。 一、XML DOM的基本概念 XML …...
认识网络安全
一 网络攻击链 踩点-工具准备-载荷投递-漏洞利用-释放载荷-建立通道-目标达成 简化下: 目标侦察:准确识别目标,收集目标详细信息,比如 网络、 邮箱、员工、社会关系、对外提供服务、漏洞 信息等,为 后续攻击做准备。…...
华为支付-免密支付接入签约代扣场景开发步骤
一、预签约(服务器开发) 1.开发者按照商户模型调用预直连商户预签约或服务商预签约接口获取preSignNo构建签约信息参数contractStr。 为保证支付订单的安全性和可靠性需要对请求body和请求头PayMercAuth对象内的入参排序拼接进行签名。请参考排序拼接和…...
9.JVM-方法区
前言 这次所讲述的是运行时数据区的最后一个部分 从线程共享与否的角度来看 ThreadLocal:如何保证多个线程在并发环境下的安全性?典型应用就是数据库连接管理,以及会话管理 栈、堆、方法区的交互关系 下面就涉及了对象的访问定位 Person&a…...
【Linux Oracle】杂货铺 日常实用2024
1.跨服务器移动文件 passwd=^T^bxxxx `/usr/bin/expect <<-EOF set timeout -1 spawn scp -r ${BATCH_TIME} sxnhtc@192.168.3.x:${EXP_MCRO_DIR}/ expect "*password:" send "$passwd\r" interact expect eof EOF` curl -k -X GET https://192.16…...
深入理解指针初阶:从概念到实践
一、引言 在 C 语言的学习旅程中,指针无疑是一座必须翻越的高峰。它强大而灵活,掌握指针,能让我们更高效地操作内存,编写出更优化的代码。但指针也常常让初学者望而生畏,觉得它复杂难懂。别担心,本文将用通…...
Git 与 Git常用命令
Git 是一个开源的分布式版本控制系统,广泛用于源代码管理。与传统的集中式版本控制系统不同,Git 允许每个开发者在本地拥有完整的代码库副本,支持离线工作和高效的分支管理。每次提交时,Git 会对当前项目的所有文件创建一个快照&a…...
jupyterLab插件开发
jupyter lab安装、配置: jupyter lab安装、配置教程_容器里装jupyterlab-CSDN博客 『Linux笔记』服务器搭建神器JupyterLab_linux_布衣小张-腾讯云开发者社区 Jupyter Lab | 安装、配置、插件推荐、多用户使用教程-腾讯云开发者社区-腾讯云 jupyterLab插件开发教…...
IDEA+DeepSeek让Java开发起飞
1.获取DeepSeek秘钥 登录DeepSeek官网 : https://www.deepseek.com/ 进入API开放平台,第一次需要注册一个账号 进去之后需要创建一个API KEY,然后把APIkey记录保存下来 接着我们获取DeepSeek的API对话接口地址,点击左边的:接口…...
机器学习数学基础:19.线性相关与线性无关
一、线性相关与线性无关的定义 (一)线性相关 想象我们有一组向量,就好比是一群有着不同“力量”和“方向”的小伙伴。给定的向量组 α ⃗ 1 , α ⃗ 2 , ⋯ , α ⃗ m \vec{\alpha}_1, \vec{\alpha}_2, \cdots, \vec{\alpha}_m α 1,α 2…...
快速集成DeepSeek到项目
DeepSeek API-KEY 获取 登录DeekSeek 官网,进入API 开放平台 2. 创建API-KEY 复制API-KEY进行保存,后期API调用使用 项目中集成DeepSeek 这里只展示部分核心代码,具体请查看源码orange-ai-deepseek-biz-starter Slf4j AllArgsConstructo…...