.net MVC IIS 无需Secret 的Microsoft登录 电脑版发表于:2024/9/13 13:28 ![.netcore](https://img.tnblog.net/arcimg/hb/c857299a86d84ee7b26d181a31e58234.jpg ".netcore") >#IIS 无需Secret 的Microsoft登录 [TOC] 核心代码 ------------ ```csharp public static class FMicsorftLoginHepler { // For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864 // The Client ID (a.k.a. Application ID) is used by the application to uniquely identify itself to Azure AD static string clientId = System.Configuration.ConfigurationManager.AppSettings["ida:ClientId"]; // RedirectUri is the URL where the user will be redirected to after they sign in static string redirectUrl = System.Configuration.ConfigurationManager.AppSettings["ida:RedirectUrl"]; // Tenant is the tenant ID (e.g. contoso.onmicrosoft.com, or 'common' for multi-tenant) static string tenant = System.Configuration.ConfigurationManager.AppSettings["ida:Tenant"]; // Authority is the URL for authority, composed by Azure Active Directory endpoint and the tenant name (e.g. https://login.microsoftonline.com/contoso.onmicrosoft.com) static string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, System.Configuration.ConfigurationManager.AppSettings["ida:Authority"], tenant); /// <summary> /// Configure OWIN to use OpenIdConnect /// </summary> /// <param name="app"></param> public static void Configuration(this IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseKentorOwinCookieSaver(); app.UseCookieAuthentication(new CookieAuthenticationOptions { CookieManager = new SystemWebCookieManager(), CookieName = "MaterialWizardWeb_AuthCookie" }); app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { // Sets the ClientId, authority, RedirectUri as obtained from web.config ClientId = clientId, Authority = authority, //RedirectUri = redirectUrl, // PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page PostLogoutRedirectUri = redirectUrl, //Scope is the requested scope: OpenIdConnectScopes.OpenIdProfileis equivalent to the string 'openid profile': in the consent screen, this will result in 'Sign you in and read your profile' Scope = OpenIdConnectScope.OpenIdProfile, // ResponseType is set to request the id_token - which contains basic information about the signed-in user ResponseType = OpenIdConnectResponseType.IdToken, // ValidateIssuer set to false to allow work accounts from any organization to sign in to your application // To only allow users from a single organizations, set ValidateIssuer to true and 'tenant' setting in web.config to the tenant name or Id (example: contoso.onmicrosoft.com) // To allow users from only a list of specific organizations, set ValidateIssuer to true and use ValidIssuers parameter TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = false }, // OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method Notifications = new OpenIdConnectAuthenticationNotifications { SecurityTokenValidated = OnSecurityTokenValidated, RedirectToIdentityProvider = OnRedirectToIdentityProvider, AuthenticationFailed = OnAuthenticationFailed } } ); } private static Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context) { ClaimsIdentity claimsId = context.AuthenticationTicket.Identity; //email dell'utente string upn = context.AuthenticationTicket.Identity.Name; string oerlikonAlias = upn.Substring(0, upn.IndexOf('@')); using (FinderContext dal = new FinderContext()) { var userobj = dal.Users.FirstOrDefault(x => x.Short_Key == oerlikonAlias); if (userobj == null) { //Save a new one userobj = new User { Keyed_Name = upn, Short_Key = oerlikonAlias }; dal.Users.Add(userobj); dal.SaveChanges(); } var roleanduser = dal.RequestPathPermissionRoleAssociatedUser.FirstOrDefault(x => x.User_ID == userobj.ID); if (roleanduser == null) { var baserole = dal.RequestPathPermissionRoles.FirstOrDefault(x => x.Default); if (baserole != null) { roleanduser = new RequestPathPermissionRoleAssociatedUser() { Role_ID = baserole.ID, User_ID = userobj.ID }; roleanduser.UpdateTime(); dal.RequestPathPermissionRoleAssociatedUser.Add(roleanduser); dal.SaveChanges(); } } else { roleanduser.UpdateTime(); dal.SaveChanges(); } claimsId.AddClaim(new Claim(ClaimTypes.Role, roleanduser.Role_ID.ToString())); } claimsId.AddClaim(new Claim(ClaimTypes.Name, oerlikonAlias)); claimsId.AddClaim(new Claim(ClaimTypes.Email, upn)); return Task.FromResult(0); } private static Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> ctx) { bool isAjaxRequest = (ctx.Request.Headers != null && ctx.Request.Headers["X-Requested-With"] == "XMLHttpRequest"); if (isAjaxRequest) { ctx.Response.Headers.Remove("Set-Cookie"); ctx.State = NotificationResultState.HandledResponse; } return Task.FromResult(0); } /// <summary> /// Handle failed authentication requests by redirecting the user to the home page with an error in the query string /// </summary> /// <param name="context"></param> /// <returns></returns> private static Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context) { context.HandleResponse(); context.Response.Redirect(GetErrorUrl(context.Exception.Message)); return Task.FromResult(0); } private static string GetErrorUrl(string errormessage) { return $"{redirectUrl}/Home/Error?errormessage={errormessage}"; } } ``` tn2>在`Startup`中启用。 ```csharp [assembly: OwinStartup(typeof(INFinderDevExpress.Startup))] namespace INFinderDevExpress { public class Startup { public void Configuration(IAppBuilder app) { app.Configuration(); app.MapSignalR(); } } } ``` 同时支持windows登录和微软登录代码如下 ------------ ```csharp public class WindowsLoginHelper { public (bool, WindowsIdentity) Login(string UserName, string Password, string Domain) { string text1 = Domain.Trim(); string text2 = UserName.Trim(); text2 = text2.Replace("/", @"/"); int num1 = text2.IndexOf("//"); if (num1 != -1) { text1 = text2.Substring(0, num1); text2 = text2.Substring(num1 + 1); } else { num1 = text2.IndexOf('@'); if (num1 != -1) { text1 = text2.Substring(num1 + 1); text2 = text2.Substring(0, num1); } } return this.authenticateUser(text2, Password.Trim(), text1); } private (bool, WindowsIdentity) authenticateUser(string UserName, string Password, string Domain) { bool flag1 = false; try { int num1; IntPtr ptr1; if (!WindowsLoginHelper.LogonUser(UserName, Domain, Password, 2, 0, out num1)) { return (flag1,null); } ptr1 = new IntPtr(num1); WindowsIdentity identity1 = new WindowsIdentity(ptr1); WindowsPrincipal principal1 = new WindowsPrincipal(identity1); HttpContext.Current.User = principal1; FormsAuthentication.SetAuthCookie(principal1.Identity.Name,false); //FormsAuthentication.RedirectFromLoginPage(UserName, false); flag1 = true; return (flag1, identity1); } catch (Exception ex) { } return (flag1, null); } public (bool, string) Login2(string UserName, string Password, string Domain) { string text1 = Domain.Trim(); string text2 = UserName.Trim(); text2 = text2.Replace("/", @"/"); int num1 = text2.IndexOf("//"); if (num1 != -1) { text1 = text2.Substring(0, num1); text2 = text2.Substring(num1 + 1); } else { num1 = text2.IndexOf('@'); if (num1 != -1) { text1 = text2.Substring(num1 + 1); text2 = text2.Substring(0, num1); } } return this.authenticateUser2(text2, Password.Trim(), text1); } private (bool, string) authenticateUser2(string UserName, string Password, string Domain) { bool flag1 = false; try { int num1; IntPtr ptr1; if (!WindowsLoginHelper.LogonUser(UserName, Domain, Password, 2, 0, out num1)) { return (flag1, null); } ptr1 = new IntPtr(num1); WindowsIdentity identity1 = new WindowsIdentity(ptr1); WindowsPrincipal principal1 = new WindowsPrincipal(identity1); HttpContext.Current.User = principal1; FormsAuthentication.SetAuthCookie(principal1.Identity.Name, false); //FormsAuthentication.RedirectFromLoginPage(UserName, false); flag1 = true; return (flag1, principal1.Identity.Name); } catch (Exception ex) { } return (flag1, null); } [DllImport("advapi32.dll")] public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out int phToken); } ``` tn2>`SelectLoginPage`是选择登录的页面。 ```csharp /// <summary> /// Send an OpenID Connect sign-in request. /// Alternatively, you can just decorate the SignIn method with the [Authorize] attribute /// </summary> public void SignIn() { if (!Request.IsAuthenticated) { HttpContext.GetOwinContext().Authentication.Challenge( new AuthenticationProperties { RedirectUri = System.Configuration.ConfigurationManager.AppSettings["ida:RedirectUrl"] }, OpenIdConnectAuthenticationDefaults.AuthenticationType); } } [AllowAnonymous] [HttpPost] public ActionResult WindowsLogin(RequestWindowsLoginModelDto dto) { var username = dto.username; var password = dto.password; var domain = "INDOM"; WindowsLoginHelper loginHelper = new WindowsLoginHelper(); var (resultpd,resultstr) = loginHelper.Login2(username, password, domain); // 如果失败重新登录 if (!resultpd) { return RedirectToAction("SelectLoginPage", "Home"); } var claims = new List<System.Security.Claims.Claim>() { new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name,resultstr), new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role,"WindowsRole") }; var claimsidentity = new System.Security.Claims.ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType); var authmanager = HttpContext.GetOwinContext().Authentication; authmanager.SignIn(claimsidentity); return RedirectToAction("Index", "Home"); } public ActionResult SelectLoginPage() { return View(); } ``` ```csharp public class RequestWindowsLoginModelDto { public string username { get; set; } public string password { get; set; } } ``` tn2>在filter中可以进行是否授权的判断。 ```csharp filterContext.HttpContext.Request.IsAuthenticated ```