简体   繁体   中英

.net web service to validate LDAP credentials using SSL

So I'm new to the whole .net thing here, but basically what I want to do is write a web service that will take a SOAP request with user's name and password and check them against an ldap server to validate that the credentials are right. I've already done this in perl, the code is below, but I'd like to replicate it in .net to get some more exposure to it. I've been poking around with c# since I've done a good amount of java programming and it seems like they are pretty similar, but if it's easier in vb or something else I'm not opposed to that.

The main problem I'm having is actually connecting to the server itself. I've found some examples online but I'm getting confused as to what I should be passing to various methods. Here is the perl version of the web service:

authenticate.cgi

use strict;
use warnings;
use SOAP::Transport::HTTP;
SOAP::Transport::HTTP::CGI
    ->dispatch_to('Authenticate')
    ->handle;

package Authenticate;

use Net::LDAPS;
use Net::LDAP;

sub Verify{
    my ($class, $user, $pass) = @_;

    my $user_dn = "uid=$user,ou=people,o=domain";

    my $ldap = Net::LDAPS->new( 'ldap.domain.com', port => '636' ) or die "$@";

    my $mesg = $ldap->bind($user_dn, password => $pass);

    return $mesg->error if $mesg->is_error;

    return "Successful authentication for user '$user'";
}

What i've been messing with in c# is the following (I might have unnecessary includes, i've been messing with a bunch of things):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.DirectoryServices;
using System.DirectoryServices.Protocols;
using System.Net;


/// <summary>
/// Summary description for WebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment     the following line. 
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {

    public WebService () {

        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }

    [WebMethod]
    public string Authenticate(string username, string pwd) {
        string domain = "LDAP://ldap.domain.com:636";
        string domainAndUsername = domain + @"\" + username;
        string path = domain + @"/ou=people,o=domain";
        string filterAttribute;
        DirectoryEntry entry = new DirectoryEntry(path, domainAndUsername, pwd);

        try
        {
            //Bind to the native AdsObject to force authentication.
            object obj = entry.NativeObject;

            DirectorySearcher search = new DirectorySearcher(entry);

            search.Filter = "(SAMAccountName=" + username + ")";
            search.PropertiesToLoad.Add("cn");
            SearchResult result = search.FindOne();

            if (null == result)
            {
                return "false";
            }

            //Update the new path to the user in the directory.
            path = result.Path;
            filterAttribute = (string)result.Properties["cn"][0];
        }
        catch (Exception ex)
        {
            throw new Exception("Error authenticating user. " + ex.Message);
        }

        return "true";
    }

}

This has been resulting in the error

System.Exception: Error authenticating user. The server is not operational.

I feel like I am just specifying the path wrong somewhere or something like that, but I can't seem to figure it out.

It seems like this would create a path that looks like "LDAP://ldap.domain.com:636\\username/ou=people,o=domain" . Typically it would be "LDAP://ldap.domain.com:636/cn=Full User Common Name,ou=People,dc=domain,dc=local" .

If you don't have the DN to start off with, you should bind anonymously or with a service credential, search using SAMAccountName , then re-bind using the username and password. Here is a good example from ASP.net. The example, however, expects the username to be in uid form, which you would want to change to SAMAccountName

Also, it looks like you are specifying a TLS port, but you have not specified AuthenticationTypes.SecureSocketsLayer , which could cause the error you are receiving.

Based on your code, you're passing the following into the DirectoryEntry constructor:

Path: LDAP://ldap.domain.com:636/ou=people,o=domain

Username: LDAP://ldap.domain.com:636\\username

That username is not right. If was Active Directory, you would put ldap.domain.com\\username but it doesn't look like this is Active Directory. So you should give the user's distinguished name. From your perl, it looks like it should be uid=username,ou=people,o=domain , but that looks weird to me. I always see it as cn=username,ou=people,o=domain .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM