diff --git a/src/CloudGaming/Api/CloudGaming.Api/Base/CloudGamingControllerBase.cs b/src/CloudGaming/Api/CloudGaming.Api/Base/CloudGamingControllerBase.cs
index 37897a2..6e76bfc 100644
--- a/src/CloudGaming/Api/CloudGaming.Api/Base/CloudGamingControllerBase.cs
+++ b/src/CloudGaming/Api/CloudGaming.Api/Base/CloudGamingControllerBase.cs
@@ -2,6 +2,7 @@ using AutoMapper;
using CloudGaming.Code.DataAccess;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace CloudGaming.Api.Base
@@ -12,6 +13,7 @@ namespace CloudGaming.Api.Base
///
[ApiController]
[Route("api/[controller]/[action]")]
+
public class CloudGamingControllerBase(IServiceProvider _serviceProvider) : ControllerBase
{
///
diff --git a/src/CloudGaming/Api/CloudGaming.Api/Controllers/AccountController.cs b/src/CloudGaming/Api/CloudGaming.Api/Controllers/AccountController.cs
index 9e60b6c..1575c37 100644
--- a/src/CloudGaming/Api/CloudGaming.Api/Controllers/AccountController.cs
+++ b/src/CloudGaming/Api/CloudGaming.Api/Controllers/AccountController.cs
@@ -40,16 +40,17 @@ public class AccountController : CloudGamingControllerBase
AccountBLL account = new AccountBLL(ServiceProvider);
return await account.SendPhoneNumber(phoneNumber.PhoneNumber);
}
-
///
- /// 登录接口
- /// 登录数据格式(设备号的目的是用于以后的多设备登录)
- /// 短信登录:{"phoneNumber":"手机号","verificationCode":"验证码","deviceNumber":"设备号"}
- /// token登录(请求标头需要带上Authorized的token) {"deviceNumber":"设备号"}
+ ///登录接口
///
+ ///
+ /// 登录数据格式(设备号的目的是用于以后的多设备登录)(设备号可不给)
+ /// 短信登录:{"phoneNumber":"手机号","verificationCode":"验证码","deviceNumber":"设备号"}
+ /// token登录(请求标头带上Authorized的token即可) {"deviceNumber":"设备号"}
+ ///
///
[HttpPost]
- public async Task LoginAsync([FromBody] BaseLoginParams baseLogin)
+ public async Task LoginAsync([FromBody] BaseLoginParams? baseLogin)
{
AccountBLL account = new AccountBLL(ServiceProvider);
return await account.LoginAsync();
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Account/AccountBLL.cs b/src/CloudGaming/Code/CloudGaming.Code/Account/AccountBLL.cs
index 0688d43..658bfac 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Account/AccountBLL.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Account/AccountBLL.cs
@@ -96,10 +96,11 @@ namespace CloudGaming.Code.Account
{
this.HttpContextAccessor.HttpContext.Request.Body.Position = 0;
var json = await new StreamReader(this.HttpContextAccessor.HttpContext.Request.Body).ReadToEndAsync();
- if (string.IsNullOrEmpty(json))
- {
- throw MessageBox.Show(ResonseCode.NullOrEmpty, "登录方式不合格");
- }
+ //this.HttpContextAccessor.HttpContext.Request.Headers.GetAuthorization();
+ //if (string.IsNullOrEmpty(json))
+ //{
+ // throw MessageBox.Show(ResonseCode.NullOrEmpty, "登录方式不合格");
+ //}
var account = AccountExtend.GetUserAccount(json, this);
if (account == null)
@@ -213,12 +214,15 @@ namespace CloudGaming.Code.Account
Ip = ip
};
await Dao.DaoUser.Context.T_User.AddAsync(user);
+ await Dao.DaoUser.Context.SaveChangesAsync();
+ await account.CreateLoginAsync(user);
}
user.LastLoginAt = DateTime.Now;
user.UpdatedAt = DateTime.Now;
user.Ip = ip;
await Dao.DaoUser.Context.SaveChangesAsync();
+
return user;
}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Account/AccountExtend.cs b/src/CloudGaming/Code/CloudGaming.Code/Account/AccountExtend.cs
index 5f60f12..ca42d6a 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Account/AccountExtend.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Account/AccountExtend.cs
@@ -23,12 +23,21 @@ namespace CloudGaming.Code.Account
///
public static IUserAccount? GetUserAccount(string jsonString, CloudGamingBase cloudGamingBase)
{
- JObject jsonObject = JObject.Parse(jsonString);
- if (AllKeysExistIgnoreCase(jsonObject, "PhoneNumber", "VerificationCode"))
+ if (!string.IsNullOrEmpty(jsonString))
{
- var loginParams = JsonConvert.DeserializeObject(jsonString);
- PhoneUserLogin phoneUserLogin = new PhoneUserLogin(loginParams, cloudGamingBase);
- return phoneUserLogin;
+ JObject jsonObject = JObject.Parse(jsonString);
+ if (AllKeysExistIgnoreCase(jsonObject, "PhoneNumber", "VerificationCode"))
+ {
+ var loginParams = JsonConvert.DeserializeObject(jsonString);
+ PhoneUserLogin phoneUserLogin = new PhoneUserLogin(loginParams, cloudGamingBase);
+ return phoneUserLogin;
+ } //检测是否还有jwt登录
+ }
+ var jwt = cloudGamingBase.HttpContextAccessor.HttpContext.Request.Headers.GetAuthorization();
+ if (!string.IsNullOrEmpty(jwt))
+ {
+ IUserAccount authorizationUserLogin = new AuthorizationUserLogin(jwt, cloudGamingBase);
+ return authorizationUserLogin;
}
return null;
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Account/Login/AuthorizationUserLogin.cs b/src/CloudGaming/Code/CloudGaming.Code/Account/Login/AuthorizationUserLogin.cs
new file mode 100644
index 0000000..176e20d
--- /dev/null
+++ b/src/CloudGaming/Code/CloudGaming.Code/Account/Login/AuthorizationUserLogin.cs
@@ -0,0 +1,87 @@
+using Alipay.EasySDK.Kernel;
+
+using CloudGaming.Code.Account.Contract;
+using CloudGaming.Code.AppExtend;
+using CloudGaming.DtoModel.Account;
+
+using HuanMeng.DotNetCore.JwtInfrastructure;
+using HuanMeng.DotNetCore.JwtInfrastructure.Interface;
+
+using Microsoft.IdentityModel.Tokens;
+
+using System;
+using System.Collections.Generic;
+using System.IdentityModel.Tokens.Jwt;
+using System.Linq;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CloudGaming.Code.Account.Login
+{
+ ///
+ /// 自动登录,只能登录,不能注册
+ ///
+ public class AuthorizationUserLogin(string token, CloudGamingBase cloudGamingBase) : IUserAccount
+ {
+ ///
+ ///
+ ///
+ public int LastLoginType { get; set; } = 0;
+
+ ///
+ ///
+ ///
+ public string DeviceNumber { get; set; }
+
+ public async Task LoginAsync()
+ {
+ if (string.IsNullOrEmpty(token))
+ {
+ throw MessageBox.Show(ResonseCode.ParamError, "登录失败");
+ }
+ var (principal, jwtToken) = cloudGamingBase.JwtAuthManager.DecodeJwtToken(token);
+ if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256Signature))
+ {
+ throw MessageBox.Show(ResonseCode.ParamError, "无效的token");
+ //throw new SecurityTokenException("无效的token");
+ }
+ var exp = principal.FindFirst("exp")?.Value;
+ if (string.IsNullOrEmpty(exp))
+ {
+ throw MessageBox.Show(ResonseCode.TwtError, "无效的token");
+ }
+ var exptime = long.Parse(exp);
+
+ long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+ if (exptime < timestamp)
+ {
+ throw MessageBox.Show(ResonseCode.TwtError, "token已经过期");
+ }
+ var _userId = principal.FindFirst("userId")?.Value;
+ var tokenMd5 = MD5Encryption.ComputeMD5Hash(token);
+ int userId = 0;
+ if (_userId == null || !int.TryParse(_userId, out userId))
+ {
+ throw MessageBox.Show(ResonseCode.TwtError, "token错误");
+ }
+ var tokenUser = await cloudGamingBase.Dao.DaoUser.Context.T_User_Token.Where(it => it.UserId == userId && it.TokenMd5 == tokenMd5).FirstOrDefaultAsync();
+ if (tokenUser == null)
+ {
+ throw MessageBox.Show(ResonseCode.UserNotLogin, "token登录失败");
+ }
+ return tokenUser?.UserId ?? 0;
+ }
+
+ public Task CreateLoginAsync(T_User user)
+ {
+ return Task.CompletedTask;
+ }
+
+ public string GetUserDataProperty(UserDataPropertyEnum userDataPropertyEnum)
+ {
+
+ return "";
+ }
+ }
+}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/Account/Login/PhoneUserLogin.cs b/src/CloudGaming/Code/CloudGaming.Code/Account/Login/PhoneUserLogin.cs
index 98455d3..bbe5235 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/Account/Login/PhoneUserLogin.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/Account/Login/PhoneUserLogin.cs
@@ -109,8 +109,6 @@ namespace CloudGaming.Code.Account.Login
}
return loginParams.DeviceNumber;
}
-
-
}
}
}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs
index b11f00c..5a79bb9 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs
@@ -154,9 +154,9 @@ namespace CloudGaming.Code.AppExtend
///
///
///
- public static DAO GetDAO(this IServiceProvider serviceProvider)
+ public static DAO GetDAO(this IServiceProvider serviceProvider, AppConfig appConfig)
{
- return new DAO(serviceProvider);
+ return new DAO(serviceProvider, appConfig);
}
diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/JwtTokenManageExtension.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/JwtTokenManageExtension.cs
index 11c9b2a..da36644 100644
--- a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/JwtTokenManageExtension.cs
+++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/JwtTokenManageExtension.cs
@@ -9,6 +9,8 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text.Json;
+using CloudGaming.Code.ExceptionExtend;
+using Microsoft.AspNetCore.Http;
namespace CloudGaming.Code.AppExtend
{
@@ -80,7 +82,7 @@ namespace CloudGaming.Code.AppExtend
}
var _userId = context.Principal.FindFirst("userId")?.Value;
int userId = 0;
- if (_userId == null && !int.TryParse(_userId, out userId))
+ if (_userId == null || !int.TryParse(_userId, out userId))
{
context.Fail("请求标头错误");
return;
@@ -89,6 +91,7 @@ namespace CloudGaming.Code.AppExtend
var appConfig = context.HttpContext.RequestServices.GetRequiredService();
var host = context.Request.Host.Host;
var app = AppConfigurationExtend.GetAppConfig(host);
+ app.ToAppConfig(appConfig);
if (app == null)
{
context.Fail("未配置租户");
@@ -102,15 +105,15 @@ namespace CloudGaming.Code.AppExtend
{
//再次去数据库中验证
//IServiceProvider
- var _serviceProvider = context.HttpContext.RequestServices.GetRequiredService();
- var dao = _serviceProvider.GetDAO();
- var c = await dao.DaoUser.Context.T_User_Token.Where(it => it.UserId == userId && it.TokenMd5 == tokenMd5).CountAsync();
+ //var _serviceProvider = context.HttpContext.RequestServices.GetRequiredService();
+ var dao = context.HttpContext.RequestServices.GetDAO(app);
+ var c = await dao.DaoUser.Context.T_User_Token.CountAsync(it => it.UserId == userId && it.TokenMd5 == tokenMd5);
if (c <= 0)
{
//添加过期信息
await redis.StringSetAsync($"user:login:{_userId}:{tokenMd5}", "0", TimeSpan.FromMinutes(15));
//app.get
- context.Fail("用户状态错误");
+ context.Fail(new LoginExpiredException(ResonseCode.LoginExpired, "用户状态错误"));
return;
}
else
@@ -123,10 +126,10 @@ namespace CloudGaming.Code.AppExtend
if (isUserExpireStatus == "0")
{
//设备被顶掉
- context.Fail("用户在其它设备登录");
+ context.Fail(new LoginExpiredException(ResonseCode.LoginExpired, "用户在其它设备登录"));
return;
}
-
+
},
// 处理认证失败的事件
OnAuthenticationFailed = context =>
@@ -134,29 +137,52 @@ namespace CloudGaming.Code.AppExtend
// 在这里可以根据需要设置自定义的HTTP状态码
context.Response.StatusCode = StatusCodes.Status403Forbidden; // 设置为 403 Forbidden
context.Response.ContentType = "application/json";
-
+ if (context.Exception is LoginExpiredException loginExpired)
+ {
+ //context.HttpContext.HandleResponse(); // 确保不再执行默认的挑战响应
+ context.Response.Clear(); // 清空现有响应内容
+ context.Response.StatusCode = StatusCodes.Status200OK; // 设置状态码为403 Forbidden
+ context.Response.ContentType = "application/json";
+ // 构建自定义的 JSON 响应
+ var str = loginExpired.ToString();
+ //var result = JsonSerializer.Serialize(new { error = context.AuthenticateFailure.Message });
+ return context.Response.WriteAsync(str); // 写入响应
+ }
+ context.Response.Clear(); // 清空现有响应内容
+ context.Response.StatusCode = StatusCodes.Status200OK; // 设置状态码为403 Forbidden
// 返回自定义的错误消息
- var result = JsonSerializer.Serialize(new { error = context.Exception?.Message });
- return context.Response.WriteAsync(result);
+ var result = new BaseResponse