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 { /// /// OAuth Provider /// public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider { #region fields /// /// 管理后台ClientId /// const string AdminPortalClientId = "witbackstage"; const string AdminPlatformId = "witplatform"; const string AppClientId = "witjitmesapp"; string clientId; /// /// 公钥 /// static string _PublicKey; /// /// 允许的clientId 列表 /// static IList _ClientIdList; #endregion #region ctor. public ApplicationOAuthProvider() { } static ApplicationOAuthProvider() { _PublicKey = "LDX2017#"; _ClientIdList = new List(); for (int i = 1; i <= 40; i++) { _ClientIdList.Add(string.Concat("wt", i.PadLeft(3, '0'))); } } #endregion /// /// 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 isn’t 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 /// /// The context of the event carries information in and results out. /// /// Task to enable asynchronous execution /// public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { //Tuple departmentInfo; var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType); try { /* var userService = ServiceLocator.Instance.GetService(); 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(); 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(); // //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 GetDepartmentInfo(BaseData.Domain.Entities.User loginUser) //{ // var departmentCode = System.Configuration.ConfigurationManager.AppSettings["DepartmentCode"]; // var departmentService = ServiceLocator.Instance.GetService(); // 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(department.ID.ToString(), department.Name); //} /// /// 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 isn’t 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 /// /// The context of the event carries information in and results out. /// /// Task to enable asynchronous execution /// 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); } /// /// 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. /// /// The context of the event carries information in and results out. /// /// Task to enable asynchronous execution /// 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); } } }