2016-08-22 7 views
5

माइक्रोसॉफ्ट बॉट फ्रेमवर्क वी 3 के साथ काम करना मैंने साइन-इन कार्ड का उपयोग शुरू किया।बॉट फ्रेमवर्क - साइन-इन कार्ड, ऑथ परिणाम कैसे प्राप्त करें

मैं एक साधारण कटौती किया था और मेरी कोड में उदाहरण कोड पेज से पेस्ट और मान लें कि यह (compiles) काम करता है: https://docs.botframework.com/en-us/csharp/builder/sdkreference/attachments.html

क्या उम्मीद थी एक व्यवहार OAuth प्रक्रिया इतनी पर पुनः निर्देशित किया करने के समान है, करना यह स्वयं की चीजें हैं और सभी सूचनाओं सहित ऑथ रेसुल लौटती हैं।

मैं क्या महसूस किया कि यह बस उस लिंक मैं प्रदान की के लिए एक नया वेब पेज खोलने, बस इतना ही है ...

कोई अन्य कोड elsewere स्थापित किया गया ...

अब तक यह मैं के रूप में बेकार लगता है इस व्यवहार के आधार पर सामान्य संदेश के साथ लिंक प्रदान कर सकता है, बॉट के साथ कोई संचार नहीं है।

क्या मुझे कुछ याद आया?

उत्तर

5

नहीं, आपको कुछ भी याद नहीं आया। साइन-इन कार्ड केवल उपयोगकर्ता को दिखाने का एक दृश्य तरीका प्रदान करता है जिसे इसे प्रमाणित करने की आवश्यकता होती है। प्रत्येक चैनल साइन-इन कार्ड को अलग-अलग प्रदर्शित करेगा; चैनल कार्यान्वयन के आधार पर।

ओएथ प्रक्रिया को लागू करने के लिए, मैं आपको AuthBot पर एक नज़र डालने की सलाह दूंगा।

AuthBot माइक्रोसॉफ्ट बॉट फ्रेमवर्क के माध्यम से बनाया बॉट पर Azure सक्रिय निर्देशिका प्रमाणीकरण के लिए एक नेट पुस्तकालय है।

भले ही आप एएडी का उपयोग नहीं कर रहे हों, फिर भी लाइब्रेरी इस विचार को प्राप्त करने के लिए उपयोगी है कि ओएथ प्रक्रिया को कैसे कार्यान्वित किया जा सकता है। आमतौर पर, एथबॉट उपयोगकर्ता को प्रमाणीकरण के लिए पूछने के लिए कुछ परिदृश्यों में साइन-इन कार्ड का उपयोग कर रहा है (this code देखें)।

+0

यू नोड – aWebDeveloper

+0

के लिए AuthBot के किसी भी प्रतिस्थापन है https://github.com को एक नजर डालें/CatalystCode/नोड authbot –

3

विकल्प 1) का उपयोग कर कस्टम प्रमाणीकरण विंडोज सक्रिय निर्देशिका:

अन्य नमूने भी मदद कर सकते हैं कि आप समझते हैं करने के लिए OAuth प्रक्रिया का निर्माण करने के लिए कैसे कर रहे हैं

मैंने कस्टम प्रमाणीकरण तकनीक बनाई है ई जो केर्बेरोज एलडीएपी प्रोटोकॉल का उपयोग करके और प्रिंसिपल कॉन्टेक्स्ट क्लास का उपयोग कर विंडोज एडी से पूछताछ करता है।

सबसे पहले, रूट संवाद में बातचीत के संदर्भ में चैट के संदर्भ को सहेजते हैं और बेस 64 एन्कोडिंग का उपयोग करके इसे एन्कोड करते हैं।

using System; 
using System.Threading.Tasks; 
using Microsoft.Bot.Builder.Dialogs; 
using Microsoft.Bot.Connector; 
using Microsoft.Bot.Builder.ConnectorEx; 
using System.Threading; 

namespace ADAuthBot.Dialogs 
{ 
    [Serializable] 
    public class RootDialog : IDialog<object> 
    { 
     public async Task StartAsync(IDialogContext context) 
     { 
      await context.PostAsync("Welcome to Auth Bot!"); 
      context.Wait(MessageReceivedAsync); 
     } 

     private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result) 
     { 
      var message = await result as Activity; 
      ConversationReference conversationReference = message.ToConversationReference(); 

      string username = string.Empty; 

      context.PrivateConversationData.SetValue<string>("usertext", message.Text); 
      if (!context.PrivateConversationData.TryGetValue<string>("Username", out username)) 
      { 
       string encodedCookie = UrlToken.Encode(conversationReference); 
       await AuthDialog.createPromptForLogin(context, encodedCookie); 
      } 

      else 
      { 
       context.Call(this, ResumeAfter); 
      } 


     } 

     private async Task ResumeAfter(IDialogContext context, IAwaitable<object> result) 
     { 
      var item = await result; 
      context.Wait(MessageReceivedAsync); 
     } 
    } 
} 

इसके बाद, हम प्रमाणीकरण संवाद जिसमें हम एक साइन-इन कार्ड बना सकते हैं और यूआरएल पेज प्रमाणित बटन को क्लिक पर खोला जाना चाहिए देने के लिए आते हैं।

using System; 
using System.Threading.Tasks; 
using Microsoft.Bot.Builder.Dialogs; 
using Microsoft.Bot.Connector; 
using Microsoft.Bot.Builder.ConnectorEx; 
using System.Threading; 
using System.Collections.Generic; 
using System.Configuration; 

namespace ADAuthBot.Dialogs 
{ 
    [Serializable] 
    public class AuthDialog: IDialog<object> 
    { 
     static string authenticationUrl = string.Empty; //Authentication URL is the MVC View URL, which will have the username and password window. 
     static string callbackurl = string.Empty; 
     static AuthDialog() 
     { 
      authenticationUrl = ConfigurationManager.AppSettings["AuthenticationUrl"]; 
      callbackurl = ConfigurationManager.AppSettings["AuthCallbackUrl"]; 
     } 
     public async Task StartAsync(IDialogContext context) 
     { 
      context.Wait(MessageReceivedAsync); 
     } 

     private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result) 
     { 
     } 

     public static async Task createPromptForLogin(IDialogContext context, string encodedCookie) 
     { 
      IMessageActivity response = context.MakeMessage(); 
      response.Attachments = new List<Attachment>(); 

      SigninCard signincard = new SigninCard() 
      { 
       Text = "Click here to sign in", 
       Buttons = new List<CardAction>() { 
         new CardAction() 
         { 
          Title = "Authentication Required", 
          Type = ActionTypes.OpenUrl, 
          Value = $"{authenticationUrl}?{encodedCookie}" 
         } 
        } 
      }; 

      response.Attachments.Add(signincard.ToAttachment()); 
      await context.PostAsync(response); 
     } 
    } 
} 

अगला मैं एक MVC दृश्य जो अपने यूज़रनेम और पासवर्ड इनपुट और विंडोज सक्रिय निर्देशिका के खिलाफ यह क्वेरी करने के लिए ADAuthController को भेज देता है बनाया है।

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 

namespace ADAuthService.Controllers 
{ 
    public class LoginADController : Controller 
    { 
     // GET: LoginAD 
     [Route("Login")] 
     public ActionResult LoginUsingAD() 
     { 
      return View(); 
     } 

    } 
} 

अगला मैं एक साधारण उस्तरा दृश्य जो जावास्क्रिप्ट के btoa() फ़ंक्शन का उपयोग करके बेस 64 एन्कोडिंग में यह एन्कोडिंग द्वारा यूज़रनेम और पासवर्ड भेजने के लिए jQuery AJAX कॉल का उपयोग करता है बनाया।

<script src="~/scripts/jquery-3.2.1.min.js"></script> 
<script src="~/scripts/bootstrap.min.js"></script> 
<link href="~/Content/bootstrap.min.css" rel="stylesheet" /> 

<script> 
     $(function() { 
      $("#txtUserName").html(""); 
      $("#txtPassword").html(""); 


      function make_base64_auth(username, password) { 
       var tok = username + ' ' + password; 
       var hash = btoa(tok); 
       return hash; 
      } 

      $("#btnSubmit").click(function() { 
       var userName = $("#txtUserName").val(); 
       var passWord = $("#txtPassword").val(); 

       var conversationReference = $(location).attr('search'); 
       console.log(conversationReference); 

       var dataToBeSent = { 
        "ConversationReference": conversationReference, 
        "HashedUserCredentials": make_base64_auth(userName, passWord) 
       }; 

       $.ajax({ 
        url: "http://localhost:1070/api/Login", 
        method: "POST", 
        dataType: "json", 
        data: dataToBeSent, 
        contentType: "application/json", 
        crossDomain: true, 
        success: function (data) { 
         debugger; 
         console.log(data); 
         if(!$.isEmptyObject(data)) 
          alert(data); 
        }, 
        error: function (jqXHR, textStatus, errorThrown) { 
         debugger; 
         if (!$.isEmptyObject(jqXHR)) 
         alert("Something happened wrong because: " + jqXHR.responseText); 
        } 
       }); 

      }); 
     }); 
</script> 
<div class="panel-info"> 
    <div class="panel panel-heading"> 
     Enter your credentials 
    </div> 
    <div class="panel panel-body"> 
     <div class="form-group"> 
      <label for="username">Username: </label> <input id="txtUserName" type="text" placeholder="Enter username" required class="form-control" /> 
      <label for="password">Password: </label> <input id="txtPassword" type="password" placeholder="Enter password" required class="form-control" /> 
      <button id="btnSubmit" class="btn btn-info">Submit</button> 
      <button id="btnReset" class="btn btn-danger" type="reset">Reset</button> 
     </div> 
    </div> 
</div> 

मैंने एक मॉडल क्लास बनाया है ताकि उपयोगकर्ता को पहचाना जा सके या नहीं।

namespace ADAuthService.Models 
{ 
    public class AuthenticatedUser 
    { 
     public string AuthenticatedUserName { get; set; } = string.Empty; 
     public bool IsAuthenticated { get; set; } = false; 
    } 
} 

और एमवीसी व्यू से विवरण प्राप्त करने के लिए एक मॉडल क्लास।

namespace ADAuthService.Models 
{ 
    public class UserDetailsHashed 
    { 
     public string HashedUserCredentials { get; set; } = string.Empty; 
     public string ConversationReference { get; set; } = string.Empty; 
    } 
} 

अब मुख्य सामग्री एक विधि लिखना है जो उपयोगकर्ता नाम, पासवर्ड और डोमेन इनपुट के रूप में ले कर Windows सक्रिय निर्देशिका से पूछताछ करता है। प्रमाणीकरण के बाद मैं ऑटोफैक आईओसी कंटेनर का उपयोग करके दायरे को हल करके प्रमाणित उपयोगकर्ता का नाम बॉट फ्रेमवर्क में भेजने के लिए सेवा यूआरएल का उपयोग कर रहा हूं।

using ADAuthService.Models; 
using Autofac; 
using Microsoft.Bot.Builder.Dialogs; 
using Microsoft.Bot.Builder.Dialogs.Internals; 
using Microsoft.Bot.Connector; 
using System; 
using System.Collections.Generic; 
using System.DirectoryServices.AccountManagement; 
using System.Linq; 
using System.Net; 
using System.Net.Http; 
using System.Security.Authentication; 
using System.Text; 
using System.Threading.Tasks; 
using System.Web.Http; 
using System.Web.Http.Cors; 

namespace ADAuthService.Controllers 
{ 
    public class ADAuthController : ApiController 
    { 
     [NonAction] 
     private void extractUserDetailsFromHash(UserDetailsHashed userDetails, out string username, out string password, out string conversationReference) 
     { 
      try 
      { 
       string[] userCredentials = userDetails.HashedUserCredentials.Split(' '); 
       byte[] userCredentialsBinary = Convert.FromBase64String(userCredentials.Last()); 
       string decodedString = Encoding.UTF8.GetString(userCredentialsBinary); 
       string[] decodedStringArray = decodedString.Split(' '); 
       username = decodedStringArray[0]; 
       password = decodedStringArray[1]; 
       string[] userConversationReference = userDetails.ConversationReference.Split('?'); 
       conversationReference = userConversationReference[1]; 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

     [NonAction] 
     private Task<AuthenticatedUser> ValidateUserAgainstAD(string username, string password) 
     { 
      AuthenticatedUser user = new AuthenticatedUser(); 
      return Task.Run<AuthenticatedUser>(() => { 
       string ADDisplayName = string.Empty; 
       try 
       { 
        using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, System.Environment.UserDomainName)) 
        { 
         bool isValidCredentials = ctx.ValidateCredentials(username, password, ContextOptions.Negotiate); 

         // Additional check to search user in directory. 
         if (isValidCredentials) 
         { 
          UserPrincipal prUsr = new UserPrincipal(ctx); 
          prUsr.SamAccountName = username; 
          PrincipalSearcher srchUser = new PrincipalSearcher(prUsr); 
          UserPrincipal foundUsr = srchUser.FindOne() as UserPrincipal; 

          if (foundUsr != null) 
          { 
           user.AuthenticatedUserName = foundUsr.DisplayName; 
           user.IsAuthenticated = isValidCredentials; 
          } 
         } 
         else 
          throw new AuthenticationException($"Couldn't query no such credentials in Microsoft Active Directory such as Username: {username} and Password: {password}. Try entering a valid username and password combination."); 
        } 
       } 
       catch (Exception ex) 
       { 
        throw ex; 
       } 
       return user; 
      });  
     } 

     [NonAction] 
     public async Task ReplyToBot(string userName, string encodedConversationReference) 
     { 
      Activity reply = null; 
      ConversationReference decodedConversationReference = UrlToken.Decode<ConversationReference>(encodedConversationReference); 
      bool writeSuccessful = false; 
      IMessageActivity msgToBeSent = decodedConversationReference.GetPostToUserMessage(); 

      using (ILifetimeScope scope = DialogModule.BeginLifetimeScope(Conversation.Container, msgToBeSent)) 
      { 
       try 
       { 
        IConnectorClient client = scope.Resolve<IConnectorClient>(); 
        IStateClient sc = scope.Resolve<IStateClient>(); 

        BotData userData = sc.BotState.GetPrivateConversationData(msgToBeSent.ChannelId, msgToBeSent.From.Id, msgToBeSent.Id); 
        userData.SetProperty("Username", userName); 
        sc.BotState.SetPrivateConversationData(msgToBeSent.ChannelId, msgToBeSent.Conversation.Id, msgToBeSent.Id, userData); 
        writeSuccessful = true; 
       } 
       catch (Exception ex) 
       { 
        writeSuccessful = false; 
        throw ex; 
       } 

       if (!writeSuccessful) 
       { 
        msgToBeSent.Text = string.Empty; 
        await Conversation.ResumeAsync(decodedConversationReference, msgToBeSent); 
       } 
       if (writeSuccessful) 
       { 
        reply = msgToBeSent as Activity; 
        var connector = new ConnectorClient(new Uri(msgToBeSent.ServiceUrl)); 
        reply.Text = $"Welcome {userName}!"; 
        connector.Conversations.SendToConversation(reply); 
       } 
      } 
     } 

     [HttpPost] 
     [EnableCors("*", "*", "*")] 
     [Route("api/Login")] 
     public async Task<HttpResponseMessage> Login(UserDetailsHashed userDetails) 
     { 
      try 
      { 
       string username = string.Empty; 
       string password = string.Empty; 
       string conversationReference = string.Empty; 
       AuthenticatedUser userToBeAuthenticated = new AuthenticatedUser(); 

       extractUserDetailsFromHash(userDetails, out username, out password, out conversationReference); 
       userToBeAuthenticated = await ValidateUserAgainstAD(username, password); 


       if (userToBeAuthenticated.IsAuthenticated) 
       { 
        await ReplyToBot(userName: userToBeAuthenticated.AuthenticatedUserName, encodedConversationReference: conversationReference); 
        return new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent($"Thanks, {userToBeAuthenticated.AuthenticatedUserName} you're now logged in!") }; 
       } 
       else 
       { 
        return new HttpResponseMessage { StatusCode = HttpStatusCode.Forbidden, Content = new StringContent($"Couldn't query no such credentials in Microsoft Active Directory such as Username: {username} and Password: {password}. Try entering a valid username and password combination.") }; 
       } 
      } 
      catch(Exception ex) 
      { 
       throw new HttpResponseException(new HttpResponseMessage() { StatusCode = HttpStatusCode.Forbidden, Content = new StringContent($"Couldn't query no such credentials in Microsoft Active Directory. Try entering a valid username and password combination.") }); 
      } 
     }   
    } 
} 

विकल्प 2) पैटर्न नीचे दिए गए लिंक में वर्णित का उपयोग करें:

MSDN Magic number Pattern

संबंधित मुद्दे