微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

php – 如何在swift中发布特殊字符的http

我正在使用以下内容将电子邮件和密码发布到我的服务器(PHP脚本).我遇到的问题是密码包含一个特殊的字符(特别是&符号),它似乎被剥离了.我认为因为它认为它的分离变量被传递了.如何在不剥离它的情况下传递这个字符?

let myURL = NSURL(string: "my script url here")
let request = NSMutableuRLRequest(URL: myURL!)
request.HTTPMethod = "POST"

let postString = "email=\(userEmailText)&password=\(userPasswordText)"

request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

解决方法:

你应该警惕使用NSURLComponents,因为NSURLQueryItem可以百分之百地逃避有问题的字符,&,它不会逃避字符(PHP将解释为符合W3C Specification for x-www-form-urlencoded的空格).正如the queryItems documentation所说:

Note

07002 specifies which characters must be percent-encoded in the query component of a URL, but not how those characters should be interpreted. The use of delimited key-value pairs is a common convention, but isn’t standardized by a specification. Therefore, you may encounter interoperability problems with other implementations that follow this convention.

One notable example of potential interoperability problems is how the plus sign (+) character is handled:

According to RFC 3986, the plus sign is a valid character within a query, and doesn’t need to be percent-encoded. However, according to the 07003, the plus sign is reserved as shorthand notation for a space within a query string (for example, ?greeting=hello+world).

如果您的值可能包含一个字符,这会为您自己添加到URL查询中的值留下一些替代值:

>您可以构建自己的要转义的CharacterSet字符集,然后在Swift 3中使用addsPercentEncodingForURLQueryValue:

extension String {

    /// Returns a new string made from the `String` by replacing all characters not in the unreserved
    /// character set (as defined by RFC3986) with percent encoded characters.

    func addingPercentEncodingForURLQueryValue() -> String? {
        let allowedCharacters = CharacterSet.urlQueryValueAllowed()
        return addingPercentEncoding(withAllowedCharacters: allowedCharacters)
    }

}

extension CharacterSet {

    /// Returns the character set for characters allowed in the individual parameters within a query URL component.
    ///
    /// The query component of a URL is the component immediately following a question mark (?).
    /// For example, in the URL `http://www.example.com/index.PHP?key1=value1#jumpLink`, the query
    /// component is `key1=value1`. The individual parameters of that query would be the key `key1`
    /// and its associated value `value1`.
    ///
    /// According to RFC 3986, the set of unreserved characters includes
    ///
    /// `ALPHA / DIGIT / "-" / "." / "_" / "~"`
    ///
    /// In section 3.4 of the RFC, it further recommends adding `/` and `?` to the list of unescaped characters
    /// for the sake of compatibility with some erroneous implementations, so this routine also allows those
    /// to pass unescaped.


    static func urlQueryValueAllowed() -> CharacterSet {
        return CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMnopQRSTUVWXYZ0123456789-._~/?")
    }

}

> Alamofire采用了类似的方法,但是从另一个方向接近它,即抓取.urlQueryAllowed字符集(接近但不太正确),并取出RFC 3986中标识的保留字符.在Swift 3中:

/// Returns a percent-escaped string following RFC 3986 for a query string key or value.
///
/// RFC 3986 states that the following characters are "reserved" characters.
///
/// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
/// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
///
/// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
/// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
/// should be percent-escaped in the query string.
///
/// - parameter string: The string to be percent-escaped.
///
/// - returns: The percent-escaped string.
public func escape(_ string: String) -> String {
    let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
    let subDelimitersToEncode = "!$&'()*+,;="

    var allowedCharacterSet = CharacterSet.urlQueryAllowed
    allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")

    var escaped = ""

    //==========================================================================================================
    //
    //  Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few
    //  hundred Chinese characters causes varIoUs malloc error crashes. To avoid this issue until iOS 8 is no
    //  longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more
    //  info, please refer to:
    //
    //      - https://github.com/Alamofire/Alamofire/issues/206
    //
    //==========================================================================================================
    if #available(iOS 8.3, *) {
        escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
    } else {
        let batchSize = 50
        var index = string.startIndex

        while index != string.endindex {
            let startIndex = index
            let endindex = string.index(index, offsetBy: batchSize, limitedBy: string.endindex) ?? string.endindex
            let range = startIndex..<endindex

            let substring = string.substring(with: range)

            escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? substring

            index = endindex
        }
    }

    return escaped
}

然后,您可以使用上面的百分比来转义键和请求正文中的值,例如:

let parameters = ["email" : email, "password" : password]
request.httpBody = parameters
    .map { (key, value) in
        let escapedKey = key.addingPercentEncodingForURLQueryValue()!
        let escapedValue = value.addingPercentEncodingForURLQueryValue()!
        return "\(escapedKey)=\(escapedValue)"
    }
    .joined(separator: "&")
    .data(using: .utf8)

对于上面的Swift 2演绎,请参阅previous revision of this answer.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐