324 lines
12 KiB
C#
324 lines
12 KiB
C#
using Masuit.Tools;
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.AspNetCore.SignalR;
|
||
using NetTaste;
|
||
using SqlSugar;
|
||
using System.Configuration;
|
||
using System.Security.Claims;
|
||
using WGShare.API.Controllers.Basic;
|
||
using WGShare.API.Helpers;
|
||
using WGShare.API.Hubs;
|
||
using WGShare.Domain.Constant;
|
||
using WGShare.Domain.DTOs.Login;
|
||
using WGShare.Domain.Entities;
|
||
using WGShare.Domain.Enums;
|
||
using WGShare.Domain.FriendlyException;
|
||
using WGShare.Domain.FriendlyException.Exceptions;
|
||
|
||
namespace WGShare.API.Controllers
|
||
{
|
||
[ApiExplorerSettings(GroupName = "public")]
|
||
[Route("auth")]
|
||
public class AuthController : BasicController
|
||
{
|
||
private readonly ISqlSugarClient _sqlSugar;
|
||
private readonly JwtHelper _jwtHelper;
|
||
private readonly IConfiguration _configuration;
|
||
private readonly IHubContext<SessionManageHub, IMessageClient> _hubContext;
|
||
private readonly ILogger<AuthController> _logger;
|
||
|
||
public AuthController(ISqlSugarClient sqlSugar, JwtHelper jwtHelper,
|
||
IConfiguration configuration,
|
||
IHubContext<SessionManageHub, IMessageClient> hubContext,
|
||
ILogger<AuthController> logger)
|
||
{
|
||
_sqlSugar = sqlSugar;
|
||
_jwtHelper = jwtHelper;
|
||
this._configuration = configuration;
|
||
this._hubContext = hubContext;
|
||
this._logger = logger;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查用户名
|
||
/// </summary>
|
||
/// <param name="account"></param>
|
||
/// <returns></returns>
|
||
[HttpGet("check-user"), AllowAnonymous]
|
||
public async Task<bool> CheckUser([FromQuery] string account)
|
||
{
|
||
return await _sqlSugar.Queryable<User>().AnyAsync(x => x.IsDelete == false && x.Account == account && x.IsAnonymous == false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 正常账号登录
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost("login"), AllowAnonymous]
|
||
public async Task<IActionResult> Login([FromBody] UserLoginDTO loginDTO)
|
||
{
|
||
var user = await _sqlSugar.Queryable<User>()
|
||
.FirstAsync(x => x.Account == loginDTO.Account && x.IsDelete == false && x.Pwd == loginDTO.Pwd && x.IsAnonymous == false);
|
||
if (user == null)
|
||
{
|
||
throw Oops.Oh("用户名或密码不正确!");
|
||
}
|
||
|
||
var tenant = await _sqlSugar.Queryable<Tenant>().FirstAsync(x => x.Id == user.TenantId);
|
||
if (tenant == null || tenant.IsDelete == true)
|
||
{
|
||
throw Oops.Oh("该区域账号已停用,请联系管理员");
|
||
}
|
||
|
||
if (await _sqlSugar.Queryable<Role>().AnyAsync(x => x.IsDelete == true && x.Id == user.RoleId))
|
||
{
|
||
throw Oops.Oh("该角色账号已停用,请联系管理员");
|
||
}
|
||
|
||
var perms = await _sqlSugar.Queryable<Permission>()
|
||
.InnerJoin<RolePrem>((m, rm) => m.Id == rm.PermId)
|
||
.Where((m, rm) => rm.RoleId == user.RoleId)
|
||
.Distinct()
|
||
.ToListAsync();
|
||
|
||
user.PermValue = perms.Sum(x => x.PermValue);
|
||
user.TenantName = tenant.TenantName;
|
||
|
||
var btnAutn = new List<Claim>();
|
||
btnAutn.Add(new Claim("perm", user.PermValue.ToString()));
|
||
btnAutn.Add(new Claim("roleid", user.RoleId));
|
||
btnAutn.Add(new Claim("tenant", user.TenantId));
|
||
btnAutn.Add(new Claim("account", user.Account));
|
||
btnAutn.Add(new Claim("uname", user.UserName));
|
||
btnAutn.Add(new Claim("ssid", user.ScreenShareId));
|
||
|
||
// 获取已登录的token
|
||
var tokens = RedisHelper.Instance.Get<AccessAndRefreshToken>(RedisKeyConstant.Data.GetAccessTokenKey(user.Id));
|
||
var accessToken = _jwtHelper.CreateToken(user.Id, btnAutn);
|
||
var refreshToken = Guid.NewGuid().ToString();
|
||
using (var pipe = RedisHelper.Instance.StartPipe())
|
||
{
|
||
if (tokens != null)
|
||
{
|
||
// 删除刷新token
|
||
pipe.Del(RedisKeyConstant.Data.GetRefreshTokenKey(tokens.RefreshToken));
|
||
}
|
||
// 设置新的刷新token
|
||
pipe.Set(RedisKeyConstant.Data.GetRefreshTokenKey(refreshToken), user, TimeSpan.FromDays(7).TotalSeconds.ToInt32());
|
||
// 记录accessToken
|
||
pipe.Set(RedisKeyConstant.Data.GetAccessTokenKey(user.Id), new AccessAndRefreshToken
|
||
{
|
||
AccessToken = accessToken,
|
||
RefreshToken = refreshToken
|
||
}, _configuration["Jwt:Expires"].ToInt32());
|
||
pipe.EndPipe();
|
||
}
|
||
|
||
// 强制下线
|
||
var connectId = RedisHelper.Instance.HGet(RedisKeyConstant.SessionManage.GetOnlineUserKey(user.TenantId), user.Id);
|
||
if (!string.IsNullOrWhiteSpace(connectId))
|
||
{
|
||
_logger.LogInformation($"账号已在其他地方登录,强制下线!account:{user.Account} connectId:{connectId}");
|
||
var roomNum = RedisHelper.Instance.Get(RedisKeyConstant.SessionManage.GetUserJoinChannelKey(user.Id));
|
||
if (!string.IsNullOrWhiteSpace(roomNum))
|
||
{
|
||
await _hubContext.Clients.Group(roomNum).UserLeave(user.Id);
|
||
}
|
||
await _hubContext.Clients.Client(connectId).ForceLogout("账号已在其他地方登录,您被迫下线!");
|
||
}
|
||
|
||
return Ok(new
|
||
{
|
||
perms = user.PermValue,
|
||
token = accessToken,
|
||
refresh_token = refreshToken,
|
||
roleId = user.RoleId,
|
||
userName = user.UserName,
|
||
tenantName = tenant.TenantName,
|
||
expire = _configuration["Jwt:Expires"].ToInt32(),
|
||
account = user.Account,
|
||
uid = user.Id,
|
||
screenShareId = user.ScreenShareId
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新token
|
||
/// </summary>
|
||
/// <param name="refreshToken"></param>
|
||
/// <returns></returns>
|
||
[HttpPost("refresh"), AllowAnonymous]
|
||
public async Task<IActionResult> Refresh([FromQuery] string refreshToken)
|
||
{
|
||
var user = RedisHelper.Instance.Get<User>(RedisKeyConstant.Data.GetRefreshTokenKey(refreshToken));
|
||
if (user == null || string.IsNullOrWhiteSpace(user.Id))
|
||
{
|
||
throw new FriendlyInternalException("登录已失效,请重新登录", null, 1403);
|
||
}
|
||
|
||
var btnAutn = new List<Claim>();
|
||
btnAutn.Add(new Claim("perm", user.PermValue.ToString()));
|
||
btnAutn.Add(new Claim("roleid", user.RoleId));
|
||
btnAutn.Add(new Claim("tenant", user.TenantId));
|
||
btnAutn.Add(new Claim("account", user.Account));
|
||
btnAutn.Add(new Claim("uname", user.UserName));
|
||
btnAutn.Add(new Claim("ssid", user.ScreenShareId));
|
||
|
||
var accessToken = _jwtHelper.CreateToken(user.Id, btnAutn);
|
||
var refreshTokenNew = Guid.NewGuid().ToString();
|
||
using (var pipe = RedisHelper.Instance.StartPipe())
|
||
{
|
||
pipe.Del(RedisKeyConstant.Data.GetRefreshTokenKey(refreshToken));
|
||
pipe.Set(RedisKeyConstant.Data.GetRefreshTokenKey(refreshTokenNew), user, TimeSpan.FromDays(7).TotalSeconds.ToInt32());
|
||
pipe.Set(RedisKeyConstant.Data.GetAccessTokenKey(user.Id), new AccessAndRefreshToken
|
||
{
|
||
AccessToken = accessToken,
|
||
RefreshToken = refreshTokenNew
|
||
}, _configuration["Jwt:Expires"].ToInt32());
|
||
|
||
pipe.EndPipe();
|
||
}
|
||
|
||
return Ok(new
|
||
{
|
||
perms = user.PermValue,
|
||
token = accessToken,
|
||
refresh_token = refreshTokenNew,
|
||
roleId = user.RoleId,
|
||
userName = user.UserName,
|
||
tenantName = user.TenantName,
|
||
expire = _configuration["Jwt:Expires"].ToInt32(),
|
||
account = user.Account,
|
||
uid = user.Id,
|
||
screenShareId = user.ScreenShareId
|
||
});
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 登出(暂未处理任何业务逻辑)
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost("logout")]
|
||
public async Task<bool> Logout()
|
||
{
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 匿名登录
|
||
/// </summary>
|
||
/// <param name="loginDTO"></param>
|
||
/// <returns></returns>
|
||
[HttpPost("anon-login"), AllowAnonymous]
|
||
public async Task<IActionResult> AnonymousLogin([FromBody] AnonymousUserLoginDTO loginDTO)
|
||
{
|
||
var room = await _sqlSugar.Queryable<Room>().Where(x => x.RoomNum == loginDTO.RoomNum && x.IsDelete == false).FirstAsync();
|
||
if (room == null)
|
||
{
|
||
throw Oops.Oh("房间不存在!");
|
||
}
|
||
|
||
var user = await _sqlSugar.Queryable<User>().Where(x => x.Account == loginDTO.DeviceId).FirstAsync();
|
||
if (user == null)
|
||
{
|
||
// 用户不存在,创建
|
||
user = new User
|
||
{
|
||
Account = loginDTO.DeviceId,
|
||
IsDelete = false,
|
||
IsAnonymous = true,
|
||
Pwd = "123456",
|
||
RoleId = "2",
|
||
UserName = loginDTO.NickName,
|
||
ScreenShareId = UserShareIdHelper.GenerateUnique8DigitNumber(),
|
||
TenantId = "123456",
|
||
};
|
||
user.Id = (await _sqlSugar.Insertable(user).ExecuteReturnIdentityAsync()).ToString();
|
||
}
|
||
else
|
||
{
|
||
if (user.IsDelete)
|
||
{
|
||
throw Oops.Oh("该设备已禁止登录!");
|
||
}
|
||
|
||
// 修改用户名
|
||
await _sqlSugar.Updateable<User>()
|
||
.SetColumns(x => x.UserName == loginDTO.NickName)
|
||
.Where(x => x.Id == user.Id)
|
||
.ExecuteCommandHasChangeAsync();
|
||
}
|
||
|
||
var btnAutn = new List<Claim>();
|
||
btnAutn.Add(new Claim("perm", "0"));
|
||
btnAutn.Add(new Claim("roleid", "2"));
|
||
btnAutn.Add(new Claim("tenant", room.TenantId));
|
||
btnAutn.Add(new Claim("account", user.Account));
|
||
btnAutn.Add(new Claim("uname", loginDTO.NickName));
|
||
btnAutn.Add(new Claim("ssid", user.ScreenShareId));
|
||
|
||
var accessToken = _jwtHelper.CreateToken(user.Id, btnAutn);
|
||
return Ok(new
|
||
{
|
||
perms = "0",
|
||
token = accessToken,
|
||
refresh_token = "",
|
||
roleId = user.RoleId,
|
||
userName = loginDTO.NickName,
|
||
tenantName = "匿名用户区域",
|
||
expire = _configuration["Jwt:Expires"].ToInt32(),
|
||
account = user.Account,
|
||
uid = user.Id,
|
||
screenShareId = user.ScreenShareId
|
||
});
|
||
}
|
||
|
||
|
||
#region 后台管理员登录接口
|
||
/// <summary>
|
||
/// 管理员登录
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost("admin/login"), AllowAnonymous]
|
||
public async Task<string> LoginForAdmin([FromBody] UserLoginDTO loginDTO)
|
||
{
|
||
var adminClient = _sqlSugar.AsTenant().GetConnection("usercenter");
|
||
|
||
var user = await adminClient.Queryable<Admin>()
|
||
.FirstAsync(x => x.Account == loginDTO.Account && x.Password == loginDTO.Pwd);
|
||
if (user == null)
|
||
{
|
||
throw Oops.Oh("用户名或密码不正确!");
|
||
}
|
||
|
||
return _jwtHelper.CreateToken(user.Id);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 管理员信息
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpGet("admin/info")]
|
||
public async Task<IActionResult> GetAdminInfo()
|
||
{
|
||
var adminClient = _sqlSugar.AsTenant().GetConnection("usercenter");
|
||
|
||
var user = await adminClient.Queryable<Admin>()
|
||
.FirstAsync(x => x.Id == UId);
|
||
if (user == null)
|
||
{
|
||
throw Oops.Oh("管理员不存在!");
|
||
}
|
||
|
||
return Ok(new
|
||
{
|
||
name = user.Name,
|
||
id = user.Id,
|
||
});
|
||
}
|
||
#endregion
|
||
}
|
||
}
|