WGShare.API/WGShare.API/Controllers/AuthController.cs

324 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}