大佬教程收集整理的这篇文章主要介绍了.net – 如何获取客户端DotNetOpenAuth.OAuth2返回的错误消息?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
context.SetError("Autorization Error","The username or password is incorrect!"); context.Rejected();
但是在客户端,我只得到协议错误(错误400)。你可以帮助我如何在授权服务器上得到服务器端的错误信息?
授权服务器的完整应用配置:
using Constants; using Microsoft.owin; using Microsoft.owin.Security; using Microsoft.owin.Security.Cookies; using Microsoft.owin.Security.Infrastructure; using Microsoft.owin.Security.oAuth; using Owin; using System; using System.Collections.Concurrent; using System.Linq; using System.Security.Claims; using System.Security.Principal; using System.Threading.Tasks; using AuthorizationServer.Entities; using AuthorizationServer.Entities.Infrastructure.Abstract; using AuthorizationServer.Entities.Infrastructure.Concrete; namespace AuthorizationServer { public partial class Startup { private IemployeeRepository Repository; public void ConfigureAuth(IAppBuilder app) { //instanciate the repository Repository = new employeeRepository(); // Enable Application Sign In Cookie app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = "Application",AuthenticationMode = AuthenticationMode.Passive,LoginPath = new PathString(Paths.LoginPath),LogoutPath = new PathString(Paths.LogoutPath),}); // Enable External Sign In Cookie app.SetDefaultSignInAsAuthenticationType("External"); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = "External",Cookiename = CookieAuthenticationDefaults.CookiePrefix + "External",ExpireTimeSpan = TimeSpan.Fromminutes(5),}); // Enable Google Authentication app.UseGoogleAuthentication(); // Setup Authorization Server app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions { AuthorizeEndpointPath = new PathString(Paths.AuthorizePath),TokenEndpointPath = new PathString(Paths.TokenPath),ApplicationCanDisplayErrors = true,#if DEBUG AllowInsecurehttp = true,#endif // Authorization server provider which controls the lifecycle of Authorization Server Provider = new OAuthAuthorizationServerProvider { OnValidateClientRedirectUri = ValidateClientRedirectUri,OnValidateClientAuthentication = ValidateClientAuthentication,OnGrantresourceownerCredentials = GrantresourceownerCredentials,OnGrantClientCredentials = GrantClientCredetails },// Authorization code provider which creates and receives authorization code AuthorizationCodeProvider = new AuthenticationTokenProvider { OnCreate = CreateAuthenticationCode,OnReceive = ReceiveAuthenticationCode,},// refresh token provider which creates and receives referesh token refreshTokenProvider = new AuthenticationTokenProvider { OnCreate = CreaterefreshToken,OnReceive = ReceiverefreshToken,} }); // inDicate our intent to use bearer authentication app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions { AuthenticationType = "Bearer",AuthenticationMode = Microsoft.owin.Security.AuthenticationMode.Active }); } private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context) { if (context.ClientId == Clients.CLIENt1.Id) { context.Validated(Clients.CLIENt1.RedirectUrl); } else if (context.ClientId == Clients.CLIENt2.Id) { context.Validated(Clients.CLIENt2.RedirectUrl); } return Task.FromResult(0); } private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { String clientname; String clientpassword; if (context.TryGetBasicCredentials(out clientname,out clientpassword) || context.TryGetFormCredentials(out clientname,out clientpassword)) { employee employee = Repository.Getemployee(clientname,clientpassword); if (employee != null) { context.Validated(); } else { context.SetError("Autorization Error","The username or password is incorrect!"); context.Rejected(); } } return Task.FromResult(0); } private Task GrantresourceownerCredentials(OAuthGrantresourceownerCredentialsContext context) { var identity = new ClaimsIdentity(new GenericIdentity(context.UserName,OAuthDefaults.AuthenticationTypE),context.Scope.SELEct(x => new Claim("urn:oauth:scope",X))); context.Validated(identity); return Task.FromResult(0); } private Task GrantClientCredetails(OAuthGrantClientCredentialsContext context) { var identity = new ClaimsIdentity(new GenericIdentity(context.ClientId,X))); context.Validated(identity); return Task.FromResult(0); } private readonly ConcurrentDictionary<String,String> _authenticationCodes = new ConcurrentDictionary<String,String>(StringComparer.ordinal); private void CreateAuthenticationCode(AuthenticationTokenCreateContext context) { context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n")); _authenticationCodes[context.Token] = context.serializeTicket(); } private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context) { String value; if (_authenticationCodes.TryRemove(context.Token,out value)) { context.DeserializeTicket(value); } } private void CreaterefreshToken(AuthenticationTokenCreateContext context) { context.SetToken(context.serializeTicket()); } private void ReceiverefreshToken(AuthenticationTokenReceiveContext context) { context.DeserializeTicket(context.Token); } } }
1)在上下文中设置错误消息
如果您在设置错误消息后调用context.Rejected(),则会删除错误消息(请参见下面的示例):
context.SetError("Account locked","You have exceeded the @R_193_10586@l allowed failed logins. Please try BACk in an hour."); context.Rejected();
您将要从您的任务中删除context.Rejected()。请注意,被拒绝和SetError方法的定义是:
拒绝:
SETERROR:
再次,通过在设置错误后调用Rejected方法,上下文将被标记为没有错误,错误消息将被删除。
而不是使用魔术字符串,我将创建一个全局属性来设置状态代码的标签。在静态全局类中,创建一个用于标识状态代码的属性(我使用X-ChALLENge,但是当然可以使用任何您选择的内容)。这将用于标记响应中添加的标题属性。
public static class ServerGlobalVariables { //Your other properties... public const String OwinChALLENgeFlag = "X-ChALLENge"; }
然后在您的OAuthAuthorizationServerProvider的各种任务中,您将添加标签作为响应中的新标头值的键。将httpStatusCode枚举与全局标志结合使用,您将可以访问所有各种状态代码,并避免使用魔术字符串。
//Set the error message context.SetError("Account locked","You have exceeded the @R_193_10586@l allowed failed logins. Please try BACk in an hour."); //Add your flag to the header of the response context.Response.Headers.Add(ServerGlobalVariables.OwinChALLENgeFlag,new[] { ((int)httpStatusCode.Unauthorized).ToString() });
在客户OwinMiddleware中,您可以使用全局变量搜索标题中的标志:
//This class handles all the OwinMiddleware responses,so the name should //not just focus on invalid authentication public class CustomAuthenticationMiddleware : OwinMiddleware { public CustomAuthenticationMiddleware(OwinMiddleware next) : base(next) { } public override async Task Invoke(IOwinContext context) { await Next.Invoke(context); if (context.Response.StatusCode == 400 && context.Response.Headers.ContainsKey( ServerGlobalVariables.OwinChALLENgeFlag)) { var headerValues = context.Response.Headers.GetValues (ServerGlobalVariables.OwinChALLENgeFlag); context.Response.StatusCode = Convert.ToInt16(headerValues.FirstOrDefault()); context.Response.Headers.Remove( ServerGlobalVariables.OwinChALLENgeFlag); } } }
最后,正如jeff指出的那样,您必须在Startup.Configuration或Startup.ConfigureAuth方法中注册此自定义OwinMiddleware:
app.Use<CustomAuthenticationMiddleware>();
使用上述解决方案,您现在可以设置状态代码和自定义错误消息,如下所示:
>无效的用户名或密码
>此帐户已超过最大尝试次数
>电子邮件帐户尚未确认
3)从ProtocolException提取错误消息
在客户端应用程序中,需要捕获并处理ProtocolException。这样的事情会给你答案:
//Need to create a class to deserialize the Json //Create this somewhere in your application public class OAuthErrorMsg { public String error { get; set; } public String error_description { get; set; } public String error_uri { get; set; } } //Need to make sure to include Newtonsoft.Json using Newtonsoft.Json; //Code for your object.... private void login() { try { var state = _webServerClient.ExchangeUserCredentialForToken( this.emailTextBox.Text,this.passwordBox.password.Trim(),scopes: new String[] { "PublicProfile" }); _accessToken = state.AccessToken; _refreshToken = state.refreshToken; } catch (ProtocolException eX) { var webException = ex.InnerException as WebException; OAuthErrorMsg error = JsonConvert.DeserializeObject<OAuthErrorMsg>( ExtractResponseString(webException)); var errormessage = error.error_description; //Now it's up to you how you process the errormessage } } public static String ExtractResponseString(WebException webException) { if (webException == null || webException.Response == null) return null; var responseStream = webException.Response.GetResponseStream() as MemoryStream; if (responseStream == null) return null; var responseBytes = responseStream.ToArray(); var responseString = Encoding.UTF8.GetString(responseBytes); return responseString; }
我已经测试了这个,它在VS2013 Pro与4.5完美的工作!
(请注意,我没有包括所有必需的命名空间或附加代码,因为这将因应用程序而异:WPF,MVC或Winform。另外,我没有讨论错误处理,所以你需要确保在您的解决方案中实施适当的错误处理。)
以上是大佬教程为你收集整理的.net – 如何获取客户端DotNetOpenAuth.OAuth2返回的错误消息?全部内容,希望文章能够帮你解决.net – 如何获取客户端DotNetOpenAuth.OAuth2返回的错误消息?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。