diff --git a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs index 7284dfe5..f340f1ca 100644 --- a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs @@ -191,11 +191,8 @@ public class SysAuthService : IDynamicApiController, ITransient [DisplayName("手机号登录")] public virtual async Task LoginPhone([Required] LoginPhoneInput input) { - var verifyCode = _sysCacheService.Get($"{CacheConst.KeyPhoneVerCode}{input.Phone}"); - if (string.IsNullOrWhiteSpace(verifyCode)) - throw Oops.Oh("验证码不存在或已失效,请重新获取!"); - if (verifyCode != input.Code) - throw Oops.Oh("验证码错误!"); + // 校验短信验证码 + App.GetRequiredService().VerifyCode(new SmsVerifyCodeInput { Phone = input.Phone, Code = input.Code }); // 账号是否存在 var user = await _sysUserRep.AsQueryable().Includes(u => u.SysOrg).ClearFilter().FirstAsync(u => u.Phone.Equals(input.Phone)); diff --git a/Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs b/Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs index 7d5308ac..b581243e 100644 --- a/Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs +++ b/Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs @@ -6,7 +6,6 @@ using Aliyun.OSS.Util; using OnceMi.AspNetCore.OSS; -using System.IO; namespace Admin.NET.Core.Service; @@ -153,7 +152,7 @@ public class SysFileService : IDynamicApiController, ITransient if (_OSSProviderOptions.IsEnable) { var filePath = string.Concat(file.FilePath, "/", file.Id.ToString() + file.Suffix); - var (stream, encoding, response) = await (await _OSSService.PresignedGetObjectAsync(file.BucketName.ToString(), filePath, 5)).GetAsStreamAsync(); + var (stream, encoding, response) = await (await _OSSService.PresignedGetObjectAsync(file.BucketName.ToString(), filePath, 5)).GetAsStreamAsync(); return new FileDownHelper().File(stream, contextType); } else @@ -538,13 +537,13 @@ public class SysFileService : IDynamicApiController, ITransient ".swf" => "application/x-shockwave-flash", ".rss" => "application/rss+xml; charset=ISO-8859-1", ".xml" => "text/xml", - //除了以上类型,都允许下载 + // 除了以上类型都允许下载 _ => "application/octet-stream", }; } } -//为了使用 ControllBase 中的方法,需要继承自 ControllBase 的对象 +// 为了使用 ControllBase 中的方法,需要继承自 ControllBase 的对象 internal class FileDownHelper : ControllerBase { -} +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Message/Dto/SmsInput.cs b/Admin.NET/Admin.NET.Core/Service/Message/Dto/SmsInput.cs new file mode 100644 index 00000000..8a6020f0 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Service/Message/Dto/SmsInput.cs @@ -0,0 +1,25 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +public class SmsVerifyCodeInput +{ + /// + /// 手机号码 + /// + /// admin + [Required(ErrorMessage = "手机号码不能为空")] + [DataValidation(ValidationTypes.PhoneNumber, ErrorMessage = "手机号码不正确")] + public string Phone { get; set; } + + /// + /// 验证码 + /// + /// 123456 + [Required(ErrorMessage = "验证码不能为空"), MinLength(4, ErrorMessage = "验证码不能少于4个字符")] + public string Code { get; set; } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs b/Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs index 20fe2542..6cf7fb93 100644 --- a/Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Message/SysSmsService.cs @@ -43,6 +43,22 @@ public class SysSmsService : IDynamicApiController, ITransient await TencentSendSms(phoneNumber); } + /// + /// 校验短信验证码 + /// + /// + /// + public bool VerifyCode(SmsVerifyCodeInput input) + { + var verifyCode = _sysCacheService.Get($"{CacheConst.KeyPhoneVerCode}{input.Phone}"); + if (string.IsNullOrWhiteSpace(verifyCode)) + throw Oops.Oh("验证码不存在或已失效,请重新获取!"); + if (verifyCode != input.Code) + throw Oops.Oh("验证码错误!"); + + return true; + } + /// /// 阿里云发送短信 📨 /// diff --git a/Web/src/api-services/apis/sys-role-api.ts b/Web/src/api-services/apis/sys-role-api.ts index da1e0236..f5821292 100644 --- a/Web/src/api-services/apis/sys-role-api.ts +++ b/Web/src/api-services/apis/sys-role-api.ts @@ -20,6 +20,7 @@ import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } fr import { AddRoleInput } from '../models'; import { AdminResultInt32 } from '../models'; import { AdminResultListInt64 } from '../models'; +import { AdminResultListListString } from '../models'; import { AdminResultListRoleOutput } from '../models'; import { AdminResultListString } from '../models'; import { AdminResultSqlSugarPagedListPageRoleOutput } from '../models'; @@ -135,7 +136,7 @@ export const SysRoleApiAxiosParamCreator = function (configuration?: Configurati }, /** * - * @summary 授权角色接口资源 🔖 + * @summary 授权角色接口 🔖 * @param {RoleApiInput} [body] * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -484,7 +485,7 @@ export const SysRoleApiAxiosParamCreator = function (configuration?: Configurati }, /** * - * @summary 获取角色接口资源集合 🔖 + * @summary 获取角色接口黑名单集合 🔖 * @param {number} id 主键Id * @param {StatusEnum} [status] 状态 * @param {*} [options] Override http request option. @@ -637,7 +638,7 @@ export const SysRoleApiAxiosParamCreator = function (configuration?: Configurati }, /** * - * @summary 获取用户接口资源集合 🔖 + * @summary 获取用户接口集合 🔖 * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -717,7 +718,7 @@ export const SysRoleApiFp = function(configuration?: Configuration) { }, /** * - * @summary 授权角色接口资源 🔖 + * @summary 授权角色接口 🔖 * @param {RoleApiInput} [body] * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -816,7 +817,7 @@ export const SysRoleApiFp = function(configuration?: Configuration) { }, /** * - * @summary 获取角色接口资源集合 🔖 + * @summary 获取角色接口黑名单集合 🔖 * @param {number} id 主键Id * @param {StatusEnum} [status] 状态 * @param {*} [options] Override http request option. @@ -859,11 +860,11 @@ export const SysRoleApiFp = function(configuration?: Configuration) { }, /** * - * @summary 获取用户接口资源集合 🔖 + * @summary 获取用户接口集合 🔖 * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiSysRoleUserApiListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + async apiSysRoleUserApiListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { const localVarAxiosArgs = await SysRoleApiAxiosParamCreator(configuration).apiSysRoleUserApiListGet(options); return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; @@ -901,7 +902,7 @@ export const SysRoleApiFactory = function (configuration?: Configuration, basePa }, /** * - * @summary 授权角色接口资源 🔖 + * @summary 授权角色接口 🔖 * @param {RoleApiInput} [body] * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -972,7 +973,7 @@ export const SysRoleApiFactory = function (configuration?: Configuration, basePa }, /** * - * @summary 获取角色接口资源集合 🔖 + * @summary 获取角色接口黑名单集合 🔖 * @param {number} id 主键Id * @param {StatusEnum} [status] 状态 * @param {*} [options] Override http request option. @@ -1003,11 +1004,11 @@ export const SysRoleApiFactory = function (configuration?: Configuration, basePa }, /** * - * @summary 获取用户接口资源集合 🔖 + * @summary 获取用户接口集合 🔖 * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async apiSysRoleUserApiListGet(options?: AxiosRequestConfig): Promise> { + async apiSysRoleUserApiListGet(options?: AxiosRequestConfig): Promise> { return SysRoleApiFp(configuration).apiSysRoleUserApiListGet(options).then((request) => request(axios, basePath)); }, }; @@ -1044,7 +1045,7 @@ export class SysRoleApi extends BaseAPI { } /** * - * @summary 授权角色接口资源 🔖 + * @summary 授权角色接口 🔖 * @param {RoleApiInput} [body] * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -1122,7 +1123,7 @@ export class SysRoleApi extends BaseAPI { } /** * - * @summary 获取角色接口资源集合 🔖 + * @summary 获取角色接口黑名单集合 🔖 * @param {number} id 主键Id * @param {StatusEnum} [status] 状态 * @param {*} [options] Override http request option. @@ -1156,12 +1157,12 @@ export class SysRoleApi extends BaseAPI { } /** * - * @summary 获取用户接口资源集合 🔖 + * @summary 获取用户接口集合 🔖 * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SysRoleApi */ - public async apiSysRoleUserApiListGet(options?: AxiosRequestConfig) : Promise> { + public async apiSysRoleUserApiListGet(options?: AxiosRequestConfig) : Promise> { return SysRoleApiFp(this.configuration).apiSysRoleUserApiListGet(options).then((request) => request(this.axios, this.basePath)); } } diff --git a/Web/src/api-services/apis/sys-sms-api.ts b/Web/src/api-services/apis/sys-sms-api.ts index 59366fd1..141b0410 100644 --- a/Web/src/api-services/apis/sys-sms-api.ts +++ b/Web/src/api-services/apis/sys-sms-api.ts @@ -17,6 +17,8 @@ import { Configuration } from '../configuration'; // Some imports not used depending on template conditions // @ts-ignore import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base'; +import { AdminResultBoolean } from '../models'; +import { SmsVerifyCodeInput } from '../models'; /** * SysSmsApi - axios parameter creator * @export @@ -223,6 +225,54 @@ export const SysSmsApiAxiosParamCreator = function (configuration?: Configuratio let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary 校验短信验证码 + * @param {SmsVerifyCodeInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + apiSysSmsVerifyCodePost: async (body?: SmsVerifyCodeInput, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/sysSms/verifyCode`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication Bearer required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + localVarHeaderParameter['Content-Type'] = 'application/json-patch+json'; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.params) { + query.set(key, options.params[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json'; + localVarRequestOptions.data = needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || ""); + return { url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, options: localVarRequestOptions, @@ -294,6 +344,20 @@ export const SysSmsApiFp = function(configuration?: Configuration) { return axios.request(axiosRequestArgs); }; }, + /** + * + * @summary 校验短信验证码 + * @param {SmsVerifyCodeInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysSmsVerifyCodePost(body?: SmsVerifyCodeInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise>> { + const localVarAxiosArgs = await SysSmsApiAxiosParamCreator(configuration).apiSysSmsVerifyCodePost(body, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, } }; @@ -344,6 +408,16 @@ export const SysSmsApiFactory = function (configuration?: Configuration, basePat async apiSysSmsTencentSendSmsPhoneNumberPost(phoneNumber: string, options?: AxiosRequestConfig): Promise> { return SysSmsApiFp(configuration).apiSysSmsTencentSendSmsPhoneNumberPost(phoneNumber, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary 校验短信验证码 + * @param {SmsVerifyCodeInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async apiSysSmsVerifyCodePost(body?: SmsVerifyCodeInput, options?: AxiosRequestConfig): Promise> { + return SysSmsApiFp(configuration).apiSysSmsVerifyCodePost(body, options).then((request) => request(axios, basePath)); + }, }; }; @@ -399,4 +473,15 @@ export class SysSmsApi extends BaseAPI { public async apiSysSmsTencentSendSmsPhoneNumberPost(phoneNumber: string, options?: AxiosRequestConfig) : Promise> { return SysSmsApiFp(this.configuration).apiSysSmsTencentSendSmsPhoneNumberPost(phoneNumber, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary 校验短信验证码 + * @param {SmsVerifyCodeInput} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SysSmsApi + */ + public async apiSysSmsVerifyCodePost(body?: SmsVerifyCodeInput, options?: AxiosRequestConfig) : Promise> { + return SysSmsApiFp(this.configuration).apiSysSmsVerifyCodePost(body, options).then((request) => request(this.axios, this.basePath)); + } } diff --git a/Web/src/api-services/models/admin-result-list-list-string.ts b/Web/src/api-services/models/admin-result-list-list-string.ts new file mode 100644 index 00000000..8e670058 --- /dev/null +++ b/Web/src/api-services/models/admin-result-list-list-string.ts @@ -0,0 +1,70 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * 全局返回结果 + * + * @export + * @interface AdminResultListListString + */ +export interface AdminResultListListString { + + /** + * 状态码 + * + * @type {number} + * @memberof AdminResultListListString + */ + code?: number; + + /** + * 类型success、warning、error + * + * @type {string} + * @memberof AdminResultListListString + */ + type?: string | null; + + /** + * 错误信息 + * + * @type {string} + * @memberof AdminResultListListString + */ + message?: string | null; + + /** + * 数据 + * + * @type {Array>} + * @memberof AdminResultListListString + */ + result?: Array> | null; + + /** + * 附加数据 + * + * @type {any} + * @memberof AdminResultListListString + */ + extras?: any | null; + + /** + * 时间 + * + * @type {Date} + * @memberof AdminResultListListString + */ + time?: Date; +} diff --git a/Web/src/api-services/models/index.ts b/Web/src/api-services/models/index.ts index 21336ffb..f669daf1 100644 --- a/Web/src/api-services/models/index.ts +++ b/Web/src/api-services/models/index.ts @@ -41,6 +41,7 @@ export * from './admin-result-list-enum-entity'; export * from './admin-result-list-enum-type-output'; export * from './admin-result-list-file-output'; export * from './admin-result-list-int64'; +export * from './admin-result-list-list-string'; export * from './admin-result-list-log-vis-output'; export * from './admin-result-list-menu-output'; export * from './admin-result-list-pos-output'; @@ -297,6 +298,7 @@ export * from './send-subscribe-message-input'; export * from './serialization-format'; export * from './signature-input'; export * from './sm-key-pair-output'; +export * from './sms-verify-code-input'; export * from './sort-version'; export * from './sql-sugar-paged-list-job-detail-output'; export * from './sql-sugar-paged-list-oauth-user-output'; diff --git a/Web/src/api-services/models/role-api-input.ts b/Web/src/api-services/models/role-api-input.ts index 12471d82..84994459 100644 --- a/Web/src/api-services/models/role-api-input.ts +++ b/Web/src/api-services/models/role-api-input.ts @@ -13,7 +13,7 @@ */ /** - * 授权角色接口资源 + * 授权角色接口黑名单 * * @export * @interface RoleApiInput diff --git a/Web/src/api-services/models/sms-verify-code-input.ts b/Web/src/api-services/models/sms-verify-code-input.ts new file mode 100644 index 00000000..dabc5096 --- /dev/null +++ b/Web/src/api-services/models/sms-verify-code-input.ts @@ -0,0 +1,40 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Admin.NET 通用权限开发平台 + * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。
👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + * + * OpenAPI spec version: 1.0.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + + /** + * + * + * @export + * @interface SmsVerifyCodeInput + */ +export interface SmsVerifyCodeInput { + + /** + * 手机号码 + * + * @type {string} + * @memberof SmsVerifyCodeInput + * @example admin + */ + phone: string; + + /** + * 验证码 + * + * @type {string} + * @memberof SmsVerifyCodeInput + * @example 123456 + */ + code: string; +} diff --git a/Web/src/api-services/models/sys-online-user.ts b/Web/src/api-services/models/sys-online-user.ts index 58ee2858..26d63258 100644 --- a/Web/src/api-services/models/sys-online-user.ts +++ b/Web/src/api-services/models/sys-online-user.ts @@ -106,4 +106,12 @@ export interface SysOnlineUser { * @memberof SysOnlineUser */ loginMode?: LoginModeEnum; + + /** + * 登录设备 + * + * @type {string} + * @memberof SysOnlineUser + */ + device?: string | null; } diff --git a/Web/src/layout/navBars/topBar/user.vue b/Web/src/layout/navBars/topBar/user.vue index c3db5f34..03525606 100644 --- a/Web/src/layout/navBars/topBar/user.vue +++ b/Web/src/layout/navBars/topBar/user.vue @@ -75,7 +75,7 @@ {{ $t('message.user.dropdown2') }} {{ $t('message.user.dropdown3') }} - {{ $t('message.user.dropdown5') }} + {{ $t('message.user.dropdown5') }} @@ -85,7 +85,7 @@