asp.Net   发布时间:2022-04-04  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了.net – 如何获取客户端DotNetOpenAuth.OAuth2返回的错误消息?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我使用ExchangeUserCredentialForToken函数从授权服务器获取令牌。当我的用户存在于我的数据库中时,它的工作正常,但当凭据不正确时,我想向客户端发回一条消息。我使用以下2行代码来设置错误消息
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);
        }
    }
}

解决方法

这是一个完整的解决方案,使用jeff的概念与我的原始帖子相结合。

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方法,上下文将被标记为没有错误,错误消息将被删除。

2)设置响应的状态代码:使用jeff的例子,用一点点旋转。

而不是使用魔术字符串,我将创建一个全局属性来设置状态代码的标签。在静态全局类中,创建一个用于标识状态代码的属性(我使用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,请注明来意。