在 swift 中从 ios 访问 Sharepoint Web 服务时被禁止访问 403

getting 403 forbidden when access sharepoint web service from ios in swift

我是 ios 开发的新手,我正在尝试从 ios 访问 Sharepoint Web 服务,但我得到 403 forbidden 响应

我也参考过this link for authentication,但是没用

然后我尝试使用我从 this link

引用的 didReceiveAuthenticationChallenge 方法进行身份验证

根据 developer.apple.com 文档,此方法已弃用,我使用 willSendRequestForAuthenticationChallenge 方法

代码如下

var message:String = "<?xml version='1.0' encoding='utf-8'?><soap12:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap12='http://www.w3.org/2003/05/soap-envelope'><soap12:Body><GetList xmlns='http://schemas.microsoft.com/sharepoint/soap/'><listName>ThemeGallery</listName></GetList></soap12:Body></soap12:Envelope>"

var urlString = "https://domainname/_vti_bin/Lists.asmx"

var url = NSURL(string: urlString)
var req = NSMutableURLRequest(URL: url!)
var msglength = String(countElements(message))

req.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
req.addValue(msglength, forHTTPHeaderField: "Content-Length")
req.addValue("http://schemas.microsoft.com/sharepoint/soap/GetList", forHTTPHeaderField: "SOAPAction")
req.HTTPMethod = "POST"
req.HTTPBody = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)

var connection = NSURLConnection(request: req, delegate: self, startImmediately: true)
    connection?.start()

连接方法

func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge) {

    if challenge.previousFailureCount == 0
    {
        var newCredential = NSURLCredential(user: self.username, password: self.password, persistence: NSURLCredentialPersistence.ForSession)
        challenge.sender.useCredential(newCredential, forAuthenticationChallenge: challenge)

    }
    else
    {
        challenge.sender.cancelAuthenticationChallenge(challenge)

    }
}

解析方法

func connectionDidFinishLoading(connection: NSURLConnection!) {

    var xmlParser = NSXMLParser(data: self.mutableData)

    xmlParser.delegate = self
    xmlParser.parse()
    xmlParser.shouldResolveExternalEntities = true 
}

检查它是否可以从像 curl 这样的实用程序的命令行调用中工作,例如

curl -D- -u user:password http://....

如果您在那里看到 403,可能是 Sharepoint 不接受 HTTP 基本身份验证,您的代码将无法运行。

I have got solution for authentication to share point web service

I have use FedAuth Cookie and rtFa Cookie to pass credential

Fisrt I have load the sharepoint login page in UIWebView

When user successfully log in. We have to get those Cookies by Below method

func verifyCookies()
{
    var rtFa:NSHTTPCookie?
    var fedAuth:NSHTTPCookie?
    let storage = NSHTTPCookieStorage.sharedHTTPCookieStorage()
    let cookieArray = storage.cookies!
    
    for tempCookie in cookieArray
    {
        if tempCookie.name == "rtFa"
        {
            rtFa = tempCookie as? NSHTTPCookie
            continue
        }
        else if tempCookie.name == "FedAuth"
        {
            fedAuth = tempCookie as? NSHTTPCookie
            continue
        }
    }
    if rtFa != nil && fedAuth != nil
    {
        self.webView.hidden = true
        self.cookieFound(rtFa!,fedAuthCookie: fedAuth!) // method mention below.
    }  
}

And after that I have use those cookie to pass credential to my request.

Below is my request code

func cookieFound(rtFaCookie:NSHTTPCookie,fedAuthCookie:NSHTTPCookie)
{
    var message:String = "<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'><listName>demo</listName><viewName></viewName><query></query><viewFields></viewFields><rowLimit></rowLimit><QueryOptions></QueryOptions><webID></webID></GetListItems></soap:Body></soap:Envelope>"
    
    var messageLength = String(countElements(message))
    var url = NSURL(string: "https://domain/_vti_bin/Lists.asmx")
    var therequest = NSMutableURLRequest(URL: url!)
    
    therequest.addValue(messageLength, forHTTPHeaderField: "Content-Length")
    therequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
    therequest.addValue("http://schemas.microsoft.com/sharepoint/soap/GetListItems", forHTTPHeaderField: "SOAPAction")
    
    // Authentication is passed in request header
    
    var cookieArray = NSArray(objects: rtFaCookie,fedAuthCookie)
    var cookieHeaders = NSHTTPCookie.requestHeaderFieldsWithCookies(cookieArray)
    var requestHeaders = NSDictionary(dictionary: cookieHeaders)
    
    
    therequest.allHTTPHeaderFields = requestHeaders
    therequest.HTTPMethod = "POST"
    therequest.HTTPBody = message.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    var connection = NSURLConnection(request: therequest, delegate: self, startImmediately: true)
    connection?.start()
    
    
}

I have called verifyCookies() method from below 'UIWebView delegate' methods

func webViewDidStartLoad(webView: UIWebView) {
    self.verifyCookies()
}
func webViewDidFinishLoad(webView: UIWebView) {
    self.verifyCookies()
}

Hope it will help someone