mh_lcmk_sms_service/APT.MicroApi/APT.OP.WebApi/Providers/ApplicationOAuthProvider.cs

231 lines
11 KiB
C#
Raw Permalink Normal View History

2024-07-12 16:37:09 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using LDX.Core;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using LDX.BaseData.Domain.IServices;
using LDX.BaseData.Domain.Entities;
using LDX.MES.Domain.IServices.FM;
namespace LDX.WebApi.Providers
{
/// <summary>
/// OAuth Provider
/// </summary>
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
#region fields
/// <summary>
/// 管理后台ClientId
/// </summary>
const string AdminPortalClientId = "witbackstage";
const string AdminPlatformId = "witplatform";
const string AppClientId = "witjitmesapp";
string clientId;
/// <summary>
/// 公钥
/// </summary>
static string _PublicKey;
/// <summary>
/// 允许的clientId 列表
/// </summary>
static IList<string> _ClientIdList;
#endregion
#region ctor.
public ApplicationOAuthProvider()
{
}
static ApplicationOAuthProvider()
{
_PublicKey = "LDX2017#";
_ClientIdList = new List<string>();
for (int i = 1; i <= 40; i++)
{
_ClientIdList.Add(string.Concat("wt", i.PadLeft(3, '0')));
}
}
#endregion
/// <summary>
/// Called when a request to the Token endpoint arrives with a "grant_type" of "password". This occurs when the user has provided name and password
/// credentials directly into the client application's user interface, and the client application is using those to acquire an "access_token" and
/// optional "refresh_token". If the web application supports the
/// resource owner credentials grant type it must validate the context.Username and context.Password as appropriate. To issue an
/// access token the context.Validated must be called with a new ticket containing the claims about the resource owner which should be associated
/// with the access token. The application should take appropriate measures to ensure that the endpoint isnt abused by malicious callers.
/// The default behavior is to reject this grant type.
/// See also http://tools.ietf.org/html/rfc6749#section-4.3.2
/// </summary>
/// <param name="context">The context of the event carries information in and results out.</param>
/// <returns>
/// Task to enable asynchronous execution
/// </returns>
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
//Tuple<string, string> departmentInfo;
var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
try
{
/*
var userService = ServiceLocator.Instance.GetService<IUserService>();
loginUser = userService.Login(context.UserName, context.Password);
if (loginUser == null)
{
throw new DomainException("用户名或密码不正确。");
}
if (IsFromAdminPortal(context) && !loginUser.CanLoginAdminPortal)
{
throw new DomainException("用户没有登录管理后台的权限。");
}
if (IsFromAdminPortal(context) && !loginUser.CanLoginAdminPortal)
{
throw new DomainException("用户没有登录管理后台的权限。");
}
if (IsFromPos(context) && !loginUser.CanLoginPos)
{
throw new DomainException("用户没有登录Pos的权限。");
} */
//departmentInfo = GetDepartmentInfo(loginUser);
//if (clientId == AdminPortalClientId || clientId == AppClientId)
//{
var userService = ServiceLocator.Instance.GetService<IFMUserService>();
var loginUser = userService.Get(i => (i.CODE.ToUpper() == context.UserName.ToUpper()
|| i.PHONE == context.UserName) && i.PASSWORD.ToUpper() == context.Password.ToUpper());
if (loginUser == null)
{
context.SetError("invalid_grant", "用户不存在或密码错误");
return;
}
else
{
oAuthIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, loginUser.ID.ToString()));
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, loginUser.NAME));
//oAuthIdentity.AddClaim(new Claim(ClaimTypes.Role, loginUser.ROLE));
//oAuthIdentity.AddClaim(new Claim(ClaimTypes.Uri, context.Request.Uri.AbsoluteUri));
oAuthIdentity.AddClaim(new Claim(LDX.Core.Security.ClaimTypes.UserCode, loginUser.CODE));
if (loginUser.ORG_ID != null)
oAuthIdentity.AddClaim(new Claim(LDX.Core.Security.ClaimTypes.OrgId, loginUser.ORG_ID.ToString()));
//oAuthIdentity.AddClaim(new Claim(LDX.Core.Security.ClaimTypes.DepartmentId, loginUser.DEPARTMENT_ID == null ? "" : loginUser.DEPARTMENT_ID.ToString()));
}
// }
// else
// {
// context.SetError("invalid_grant", "用户不存在或密码错误");
// return;
// //var platformUserService = ServiceLocator.Instance.GetService<IPlatformUserService>();
// //var platUser = platformUserService.Get(i => i.LOGIN_NAME.ToUpper() == context.UserName.ToUpper() && i.PASSWORD == context.Password.ToUpper());
// //if (platUser == null)
// //{
// // context.SetError("invalid_grant", "用户不存在或密码错误");
// // return;
// //}
// //else
// //{
// // oAuthIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, platUser.ID.ToString()));
// // //oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, platUser.NAME));
// // oAuthIdentity.AddClaim(new Claim(LDX.Core.Security.ClaimTypes.UserCode, platUser.LOGIN_NAME));
// // oAuthIdentity.AddClaim(new Claim(LDX.Core.Security.ClaimTypes.Cid, platUser.CID));
// //}
//}
}
catch (DomainException domainEx)
{
context.SetError("invalid_grant", domainEx.Message);
return;
}
catch (Exception ex)
{
context.SetError("invalid_grant", ex.Message);
return;
}
var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
context.Validated(ticket);
await base.GrantResourceOwnerCredentials(context);
}
private bool IsFromAdminPortal(OAuthGrantResourceOwnerCredentialsContext context)
{
return AdminPortalClientId.Equals(context.ClientId);
}
private bool IsFromPos(OAuthGrantResourceOwnerCredentialsContext context)
{
return !IsFromAdminPortal(context);
}
//private Tuple<string, string> GetDepartmentInfo(BaseData.Domain.Entities.User loginUser)
//{
// var departmentCode = System.Configuration.ConfigurationManager.AppSettings["DepartmentCode"];
// var departmentService = ServiceLocator.Instance.GetService<IDepartmentService>();
// var department = string.IsNullOrWhiteSpace(departmentCode) ? departmentService.Get(loginUser.DepartmentID) : departmentService.Query(p => p.Code == departmentCode).FirstOrDefault();
// if (department == null)
// throw new DomainException("服务端异常,未找到配置的门店信息。");
// return new Tuple<string, string>(department.ID.ToString(), department.Name);
//}
/// <summary>
/// Called when a request to the Token endpoint arrives with a "grant_type" of "client_credentials". This occurs when a registered client
/// application wishes to acquire an "access_token" to interact with protected resources on it's own behalf, rather than on behalf of an authenticated user.
/// If the web application supports the client credentials it may assume the context.ClientId has been validated by the ValidateClientAuthentication call.
/// To issue an access token the context.Validated must be called with a new ticket containing the claims about the client application which should be associated
/// with the access token. The application should take appropriate measures to ensure that the endpoint isnt abused by malicious callers.
/// The default behavior is to reject this grant type.
/// See also http://tools.ietf.org/html/rfc6749#section-4.4.2
/// </summary>
/// <param name="context">The context of the event carries information in and results out.</param>
/// <returns>
/// Task to enable asynchronous execution
/// </returns>
public override Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
{
var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, context.ClientId));
var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
context.Validated(ticket);
return base.GrantClientCredentials(context);
}
/// <summary>
/// Called to validate that the origin of the request is a registered "client_id", and that the correct credentials for that client are
/// present on the request. If the web application accepts Basic authentication credentials,
/// context.TryGetBasicCredentials(out clientId, out clientSecret) may be called to acquire those values if present in the request header. If the web
/// application accepts "client_id" and "client_secret" as form encoded POST parameters,
/// context.TryGetFormCredentials(out clientId, out clientSecret) may be called to acquire those values if present in the request body.
/// If context.Validated is not called the request will not proceed further.
/// </summary>
/// <param name="context">The context of the event carries information in and results out.</param>
/// <returns>
/// Task to enable asynchronous execution
/// </returns>
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientSecret;
context.TryGetBasicCredentials(out clientId, out clientSecret);
//if (AdminPortalClientId.Equals(clientId) || AppClientId.Equals(clientId) || AdminPlatformId.Equals(clientId))//管理后台,授权通过
//{
context.Validated(clientId);
//}
//else if (_ClientIdList.Contains(clientId) && _PublicKey.Equals(clientSecret))//校验POS前端私钥和公钥
//{
// context.Validated(clientId);
//}
return base.ValidateClientAuthentication(context);
}
}
}