当前位置: 首页 > 编程语言 > C#

结合FormsAuthentication和BasicAuthentication分享

时间:2023-04-11 00:48:11 C#

CombiningFormsAuthenticationandBasicAuthenticationvalidation)public.我想出的解决方案似乎有效,但我在这里遗漏了什么吗?首先,整个站点在HTTPS下运行。该站点设置为在web.config中使用表单身份验证,然后覆盖Global.asax中的AuthenticateRequest以在Web服务页面上触发基本身份验证:voidApplication_AuthenticateRequest(objectsender,EventArgse){//检查是否请求Web服务-这是唯一应该接受基本身份验证的页面//HttpApplicationapp=(HttpApplication)sender;if(app.Context.Request.Path.StartsWith("/Service/MyService.asmx")){if(HttpContext.Current.User!=null){Logger.Debug("Webservicerequestedbyuser"+HttpContext.Current.User.Identity.Name);}else{Logger.Debug("Nulluser-usebasicauth");HttpContextctx=HttpContext.Current;布尔认证=假;//查找授权标头字符串authHeader=ctx.Request.Headers["Authorization"];if(authHeader!=null&&authHeader.StartsWith("Basic")){//从标头中提取凭据string[]credentials=extractCredentials(authHeader);//因为我仍在使用表单提供程序,所以这应该//va以与表单登录相同的方式进行更新if(Membership.ValidateUser(credentials[0],credentials[1])){//创建主体-也可以获得用户GenericIdentityid=newGenericIdentity(credentials[0],"自定义基础");GenericPrincipalp=newGenericPrincipal(id,null);ctx.User=p;认证=真;}}//发出身份验证标头以触发客户端身份验证if(authenticated==false){ctx.Response.StatusCode=401;ctx.Response.AddHeader("WWW-Authenticate","Basicrealm="localhost"");ctx.Response.Flush();ctx.Response.Close();返回;}}}}privatestring[]extractCredentials(stringauthHeader){//去掉“基本”字符串encodedUserPass=authHeader.Substring(6).Trim();//这是正确的编码Encodingencoding=Encoding.GetEncoding("iso-8859-1");字符串userPass=encoding.GetString(Convert.FromBase64String(encodedUserPass));intseparator=userPass.IndexOf(':');字符串[]凭证=新字符串[2];credentials[0]=userPass.Substring(0,separator);credentials[1]=userPass.Substring(separator+1);返回凭据;}.Net4.5有一个新的Response属性:SuppressFormsAuthenticationRedirect当设置为true时,它??将防止将401响应重定向到站点的登录页面。您可以在global.asax.cs中使用以下代码片段来启用基本身份验证,例如/HealthCheck文件夹。//////验证应用程序请求。///基本身份验证用于以“/HealthCheck”开头的请求。///HealthCheck文件夹的IIS身份验证设置:///-Windows身份验证:已禁用。///-基本身份验证:已启用。//////事件的来源。///一个包含事件数据的。protectedvoidApplication_AuthenticateRequest(objectsender,EventArgse){varapplication=(HttpApplication)sender;如果(application.Context.Request.Path.StartsWith("/HealthCheck",StringComparison.OrdinalIgnoreCase)){如果(HttpContext.Current.User==null){varcontext=HttpContext.Current;context.Response.SuppressFormsAuthenticationRedirect=true;我根据OP的想法和SamuelMeacham的指示得到了一个解决方案。在global.asax.cs中:protectedvoidApplication_AuthenticateRequest(objectsender,EventArgse){if(DoesUrlNeedBasicAuth()&&Request.IsSecureConnection)//在我们尝试使用基本身份验证之前强制使用https{if(HttpContext.Current.User!=null&&HttpContext.Current.User.Identity.IsAuthenticated){_log.Debug("用户请求的Web服务"+HttpContext.Current.User.Identity.Name);}else{_log.Debug("Nulluser-usebasicauth");HttpContextctx=HttpContext.Current;布尔认证=假;//查找授权标头字符串authHeader=ctx.Request.Headers["Authorization"];if(authHeader!=null&&authHeader.StartsWith("Basic")){//从标头中提取凭据string[]credentials=extractCredentials(authHeader);//查找凭据(我们现在将在配置中执行此操作)//首先检查本地配置varlocalAuthSection=ConfigurationManager.GetSection("apiUsers")asApiUsersSection;认证=检查AuthSectionForCredentials(凭证[0],凭证[1],localAuthSection);if(!authenticated){//检查子配置varwebAuth=System.Web.Configuration.WebConfigurationManager.GetSection("apiUsers")asApiUsersSection;认证=CheckAuthSectionForCredentials(凭据[0],凭据[1],webAuth);}}//发出身份验证标头以触发客户端身份验证if(authenticated==false){ctx.Response.StatusCode=401;ctx.Response.AddHeader("WWW-Authenticate","Basicrealm="localhost"");ctx.Response.Flush();ctx.Response.Close();返回;}}}else{//什么都不做}}//////检测当前请求是否需要基本身份验证而不是表单身份验证。///这是在web.config文件中确定的,用于拒绝表单身份验证的文件夹或页面。///publicboolDoesUrlNeedBasicAuth(){HttpContextcontext=HttpContext.Current;字符串路径=context.Request.AppRelativeCurrentExecutionFilePath;如果(故事xt.SkipAuthorization)返回false;//如果路径被标记为基本身份验证,强制它if(context.Request.Path.StartsWith(Request.ApplicationPath+"/integration",true,CultureInfo.CurrentCulture))returntrue;//forcebasic//ifnoprincipalaccesswasgrantedforcebasicauth//if(!UrlAuthorizationModule.CheckUrlAccessForPrincipal(path,context.User,context.Request.RequestType))returntrue;返回假;}privatestring[]extractCredentials(stringauthHeader){//去掉“基本”字符串encodedUserPass=authHeader.Substring(6).Trim();//这是正确的编码Encodingencoding=Encoding.GetEncoding("iso-8859-1");字符串userPass=encoding.GetString(Convert.FromBase64String(encodedUserPass));intseparator=userPass.IndexOf(':');字符串[]凭证=新字符串[2];credentials[0]=userPass.Substring(0,separator);credentials[1]=userPass.Substring(separator+1);返回凭据;}//////检查给定的基本au可以授予论文详细信息访问权限。如果为真,则将GenericPrincipal分配给上下文。///privateboolCheckAuthSectionForCredentials(stringusername,stringpassword,ApiUsersSectionsection){if(section==null)returnfalse;foreach(ApiUserElementuserinsection.Users){if(user.UserName==username&&user.Password==password){Context.User=newGenericPrincipal(newGenericIdentity(user.Name,"Basic"),user.Roles.分裂(','));返回真;}}返回假;允许访问的凭据存储在web.config的自定义部分中,但您可以根据需要存储它们,上面的代码需要HTTPS,但如果您愿意,可以删除此限制。编辑但是正如评论中正确指出的那样,由于用户名和密码是经过编码的并且以纯文本形式可见,所以这可能不是一个好主意。当然,即使这里有HTTPS限制,您也无法阻止外部请求尝试使用不安全的HTTP并与任何观看流量的人共享他们的凭据。现在,执行基本身份验证的路径在这里是硬编码的,但显然可以放在配置或其他源中。在我的例子中,“集成”文件夹被设置为允许匿名用户。这里有一行注释引用CheckUrlAccessForPrincipal,如果用户未通过表单身份验证登录,则使用基本身份验证授予对站点上任何页面的访问权限。使用Application_AuthenticateRequest而不是Application_AuthorizeRequest最终变得很重要,因为Application_AuthorizeRequest会强制进行基本身份验证,但无论如何都会重定向到表单身份验证登录页面。通过在web.config中使用基于位置的权限,我没有成功地让它工作,但从未找到原因。切换到Application_AuthenticateRequest就可以了,所以我把它留在那里。这样做的结果给我留下了一个文件夹,可以在通常使用表单身份验证的应用程序中使用基本身份验证通过HTTPS访问该文件夹。登录用户无论如何都可以访问该文件夹。希望这可以帮助。我认为你走在正确的道路上。但是,我不确定您是否应该在身份验证请求中这样做。这是在识别用户时,而不是在检查资源权限时(稍后在授权请求中)。首先,在您的web.config中,使用表单身份验证删除您想要使用基本身份验证的资源。Web.config文件Global.asax.cs或任何地方(IHttpModule等)然后,在Application_AuthorizeRequest中,不是对特定处理程序进行硬编码或尝试解析URL以查看您是否在特定文件夹中,以下将默认设置所有内容安全性(表单身份验证第一,基本身份验证,如果表单身份验证已通过web.config中的设置删除。//////检查当前请求是否可以跳过授权,因为context.SkipAuthorization为true,///或者因为UrlAuthorizationModule.CheckUrlAccessForPrincipal()为当前请求/用户/url返回true。/////publicboolDoesUrlRequireAuth(){HttpContextcontext=HttpContext.Current;字符串路径=context.Request.AppRelativeCurrentExecutionFilePath;返回上下文。SkipAuthorization||UrlAuthorizationModule.CheckUrlAccessForPrincipal(路径,context.User,context.Request.RequestType);}voidApplication_AuthorizeRequest(objectsender,EventArgse){if(DoesUrlRequireAuth()){//请求受表单授权保护}else{//在这里做你的http基本授权代码}}没有测试(只是在这里输入内联),但是我已经完成了很多自定义会员提供程序,您所要求的是完全可行的。希望有的对你有用=)以上就是C#学习教程:综合了表单认证和基本认证分享的所有内容,如果对你有用,需要进一步了解C#学习教程,希望你点赞更多关注——本文来自网络合集,不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: