热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

我可以设置WKWebView要使用的cookie吗?-CanIsetthecookiestobeusedbyaWKWebView?

ImtryingtoswitchanexistingappfromUIWebViewtoWKWebView.Thecurrentappmanagestheusers

I'm trying to switch an existing app from UIWebView to WKWebView. The current app manages the users login / session outside of the web view and sets the COOKIEs required for authentication into the the NSHTTPCOOKIEStore. Unfortunately new WKWebView doesn't use the COOKIEs from the NSHTTPCOOKIEStorage. Is there another way to achieve this?

我想把一个现有的应用从UIWebView切换到WKWebView。当前应用程序管理web视图之外的用户登录/会话,并将验证所需的COOKIE设置为NSHTTPCOOKIEStore。不幸的是,新的WKWebView不使用来自NSHTTPCOOKIEStorage的COOKIE。还有其他方法可以实现这一点吗?

11 个解决方案

#1


86  

Edit for iOS 11+ only

只对ios11 +进行编辑

Use WKHTTCOOKIEStore:

使用WKHTTCOOKIEStore:

let COOKIE = HTTPCOOKIE(properties: [
    .domain: "example.com",
    .path: "/",
    .name: "MyCOOKIEName",
    .value: "MyCOOKIEValue",
    .secure: "TRUE",
    .expires: NSDate(timeIntervalSinceNow: 31556926)
])! 

webView.configuration.websiteDataStore.httpCOOKIEStore.setCOOKIE(COOKIE)

Since you are pulling them over from HTTPCookeStorage, you can do this:

因为您正在从HTTPCookeStorage将它们拉过来,所以您可以这样做:

let COOKIEs = HTTPCOOKIEStorage.shared.COOKIEs ?? []
for (COOKIE) in COOKIEs {
    webView.configuration.websiteDataStore.httpCOOKIEStore.setCOOKIE(COOKIE)
}

Old answer for iOS 10 and below

iOS 10和以下的旧答案

If you require your COOKIEs to be set on the initial load request, you can set them on NSMutableURLRequest. Because COOKIEs are just a specially formatted request header this can be achieved like so:

如果您要求在初始加载请求上设置COOKIE,您可以在NSMutableURLRequest上设置它们。因为COOKIE只是一个特殊格式的请求头,所以可以这样实现:

WKWebView * webView = /*set up your webView*/
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com/index.html"]];
[request addValue:@"TeskCOOKIEKey1=TeskCOOKIEValue1;TeskCOOKIEKey2=TeskCOOKIEValue2;" forHTTPHeaderField:@"COOKIE"];
// use stringWithFormat: in the above line to inject your values programmatically
[webView loadRequest:request];

If you require subsequent AJAX requests on the page to have their COOKIEs set, this can be achieved by simply using WKUserScript to set the values programmatically via Javascript at document start like so:

如果需要对页面上的后续AJAX请求设置COOKIE,可以通过简单地使用WKUserScript在document start时通过Javascript以编程方式设置值,如:

WKUserContentController* userCOntentController= WKUserContentController.new;
WKUserScript * COOKIEScript = [[WKUserScript alloc] 
    initWithSource: @"document.COOKIE = 'TeskCOOKIEKey1=TeskCOOKIEValue1';document.COOKIE = 'TeskCOOKIEKey2=TeskCOOKIEValue2';"
    injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
// again, use stringWithFormat: in the above line to inject your values programmatically
[userContentController addUserScript:COOKIEScript];
WKWebViewConfiguration* webViewCOnfig= WKWebViewConfiguration.new;
webViewConfig.userCOntentController= userContentController;
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];

Combining these two techniques should give you enough tools to transfer COOKIE values from Native App Land to Web View Land. You can find more info on the COOKIE Javascript api on mozilla's page, if you require some more advanced COOKIEs.

结合这两种技术,您将有足够的工具将COOKIE值从本地应用程序域传输到Web视图域。如果您需要一些更高级的COOKIE,您可以在mozilla页面上找到关于COOKIE Javascript api的更多信息。

Yeah it sucks that Apple is not supporting many of the niceties of UIWebView. Not sure if they will ever support them, but hopefully they will get on this soon. Hope this helps!

是的,苹果没有支持UIWebView的很多优点,这太糟糕了。不确定他们是否会支持他们,但希望他们很快就能做到。希望这可以帮助!

#2


53  

After playing with this answer (which was fantastically helpful :) we've had to make a few changes:

在尝试了这个答案(非常有用)之后,我们必须做一些改变:

  • We need the web views to deal with multiple domains without leaking private COOKIE information between those domains
  • 我们需要web视图来处理多个域,而不泄漏这些域之间的私有COOKIE信息
  • We need it to honour secure COOKIEs
  • 我们需要它来保护安全的饼干
  • If the server changes a COOKIE value we want our app to know about it in NSHTTPCOOKIEStorage
  • 如果服务器改变了一个COOKIE值,我们希望我们的应用程序在NSHTTPCOOKIEStorage中知道它
  • If the server changes a COOKIE value we don't want our scripts to reset it back to it's original value when you follow a link / AJAX etc.
  • 如果服务器更改了一个COOKIE值,我们不希望我们的脚本在您遵循链接/ AJAX等时将其重置为原始值。

So we modified our code to be this;

我们把代码修改成这样;

Creating a request

NSMutableURLRequest *request = [originalRequest mutableCopy];
NSString *validDomain = request.URL.host;
const BOOL requestIsSecure = [request.URL.scheme isEqualToString:@"https"];

NSMutableArray *array = [NSMutableArray array];
for (NSHTTPCOOKIE *COOKIE in [[NSHTTPCOOKIEStorage sharedHTTPCOOKIEStorage] COOKIEs]) {
    // Don't even bother with values containing a `'`
    if ([COOKIE.name rangeOfString:@"'"].location != NSNotFound) {
        NSLog(@"Skipping %@ because it contains a '", COOKIE.properties);
        continue;
    }

    // Is the COOKIE for current domain?
    if (![COOKIE.domain hasSuffix:validDomain]) {
        NSLog(@"Skipping %@ (because not %@)", COOKIE.properties, validDomain);
        continue;
    }

    // Are we secure only?
    if (COOKIE.secure && !requestIsSecure) {
        NSLog(@"Skipping %@ (because %@ not secure)", COOKIE.properties, request.URL.absoluteString);
        continue;
    }

    NSString *value = [NSString stringWithFormat:@"%@=%@", COOKIE.name, COOKIE.value];
    [array addObject:value];
}

NSString *header = [array componentsJoinedByString:@";"];
[request setValue:header forHTTPHeaderField:@"COOKIE"];

// Now perform the request...

This makes sure that the first request has the correct COOKIEs set, without sending any COOKIEs from the shared storage that are for other domains, and without sending any secure COOKIEs into an insecure request.

这样可以确保第一个请求设置了正确的COOKIE,而不会从共享存储中发送任何其他域的COOKIE,也不会向不安全请求发送任何安全COOKIE。

Dealing with further requests

We also need to make sure that other requests have the COOKIEs set. This is done using a script that runs on document load which checks to see if there is a COOKIE set and if not, set it to the value in NSHTTPCOOKIEStorage.

我们还需要确保其他请求具有COOKIE集。

// Get the currently set COOKIE names in Javascriptland
[script appendString:@"var COOKIENames = document.COOKIE.split('; ').map(function(COOKIE) { return COOKIE.split('=')[0] } );\n"];

for (NSHTTPCOOKIE *COOKIE in [[NSHTTPCOOKIEStorage sharedHTTPCOOKIEStorage] COOKIEs]) {
    // Skip COOKIEs that will break our script
    if ([COOKIE.value rangeOfString:@"'"].location != NSNotFound) {
        continue;
    }

    // Create a line that appends this COOKIE to the web view's document's COOKIEs
    [script appendFormat:@"if (COOKIENames.indexOf('%@') == -1) { document.COOKIE='%@'; };\n", COOKIE.name, COOKIE.wn_JavascriptString];
}

WKUserContentController *userCOntentController= [[WKUserContentController alloc] init];
WKUserScript *COOKIEInScript = [[WKUserScript alloc] initWithSource:script
                                                      injectionTime:WKUserScriptInjectionTimeAtDocumentStart
                                                   forMainFrameOnly:NO];
[userContentController addUserScript:COOKIEInScript];

...

// Create a config out of that userContentController and specify it when we create our web view.
WKWebViewConfiguration *cOnfig= [[WKWebViewConfiguration alloc] init];
config.userCOntentController= userContentController;

self.webView = [[WKWebView alloc] initWithFrame:webView.bounds configuration:config];

Dealing with COOKIE changes

We also need to deal with the server changing a COOKIE's value. This means adding another script to call back out of the web view we are creating to update our NSHTTPCOOKIEStorage.

我们还需要处理服务器更改COOKIE值的问题。这意味着添加另一个脚本,以从我们正在创建的web view中调用,以更新我们的NSHTTPCOOKIEStorage。

WKUserScript *COOKIEOutScript = [[WKUserScript alloc] initWithSource:@"window.webkit.messageHandlers.updateCOOKIEs.postMessage(document.COOKIE);"
                                                       injectionTime:WKUserScriptInjectionTimeAtDocumentStart
                                                    forMainFrameOnly:NO];
[userContentController addUserScript:COOKIEOutScript];

[userContentController addScriptMessageHandler:webView
                                          name:@"updateCOOKIEs"];

and implementing the delegate method to update any COOKIEs that have changed, making sure that we are only updating COOKIEs from the current domain!

并实现委托方法来更新任何已更改的COOKIE,确保我们只更新来自当前域的COOKIE !

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSArray *COOKIEs = [message.body componentsSeparatedByString:@"; "];
    for (NSString *COOKIE in COOKIEs) {
        // Get this COOKIE's name and value
        NSArray *comps = [COOKIE componentsSeparatedByString:@"="];
        if (comps.count <2) {
            continue;
        }

        // Get the COOKIE in shared storage with that name
        NSHTTPCOOKIE *localCOOKIE = nil;
        for (NSHTTPCOOKIE *c in [[NSHTTPCOOKIEStorage sharedHTTPCOOKIEStorage] COOKIEsForURL:self.wk_webView.URL]) {
            if ([c.name isEqualToString:comps[0]]) {
                localCOOKIE = c;
                break;
            }
        }

        // If there is a COOKIE with a stale value, update it now.
        if (localCOOKIE) {
            NSMutableDictionary *props = [localCOOKIE.properties mutableCopy];
            props[NSHTTPCOOKIEValue] = comps[1];
            NSHTTPCOOKIE *updatedCOOKIE = [NSHTTPCOOKIE COOKIEWithProperties:props];
            [[NSHTTPCOOKIEStorage sharedHTTPCOOKIEStorage] setCOOKIE:updatedCOOKIE];
        }
    }
}

This seems to fix our COOKIE problems without us having to deal with each place we use WKWebView differently. We can now just use this code as a helper to create our webviews and it transparently updates NSHTTPCOOKIEStorage for us.

这似乎可以解决我们的COOKIE问题,而不必处理我们使用WKWebView的每个地方。我们现在可以使用这个代码作为一个助手来创建我们的webview,它会透明地为我们更新NSHTTPCOOKIEStorage。


EDIT: Turns out I used a private category on NSHTTPCOOKIE - here's the code:

编辑:原来我在NSHTTPCOOKIE上使用了一个私有类别——下面是代码:

- (NSString *)wn_JavascriptString {
    NSString *string = [NSString stringWithFormat:@"%@=%@;domain=%@;path=%@",
                        self.name,
                        self.value,
                        self.domain,
                        self.path ?: @"/"];

    if (self.secure) {
        string = [string stringByAppendingString:@";secure=true"];
    }

    return string;
}

#3


19  

work for me

为我工作

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
    let headerFields = navigationAction.request.allHTTPHeaderFields
    var headerIsPresent = contains(headerFields?.keys.array as! [String], "COOKIE")

    if headerIsPresent {
        decisionHandler(WKNavigationActionPolicy.Allow)
    } else {
        let req = NSMutableURLRequest(URL: navigationAction.request.URL!)
        let COOKIEs = yourCOOKIEData
        let values = NSHTTPCOOKIE.requestHeaderFieldsWithCOOKIEs(COOKIEs)
        req.allHTTPHeaderFields = values
        webView.loadRequest(req)

        decisionHandler(WKNavigationActionPolicy.Cancel)
    }
}

#4


13  

Here is my version of Mattrs solution in Swift for injecting all COOKIEs from HTTPCOOKIEStorage. This was done mainly to inject an authentication COOKIE to create a user session.

这是我在Swift中的Mattrs解决方案版本,用于从HTTPCOOKIEStorage注入所有COOKIE。这主要是为了注入一个身份验证COOKIE来创建一个用户会话。

public func setupWebView() {
    let userCOntentController= WKUserContentController()
    if let COOKIEs = HTTPCOOKIEStorage.shared.COOKIEs {
        let script = getJSCOOKIEsString(for: COOKIEs)
        let COOKIEScript = WKUserScript(source: script, injectionTime: .atDocumentStart, forMainFrameOnly: false)
        userContentController.addUserScript(COOKIEScript)
    }
    let webViewCOnfig= WKWebViewConfiguration()
    webViewConfig.userCOntentController= userContentController

    self.webView = WKWebView(frame: self.webViewContainer.bounds, configuration: webViewConfig)
}

///Generates script to create given COOKIEs
public func getJSCOOKIEsString(for COOKIEs: [HTTPCOOKIE]) -> String {
    var result = ""
    let dateFormatter = DateFormatter()
    dateFormatter.timeZOne= TimeZone(abbreviation: "UTC")
    dateFormatter.dateFormat = "EEE, d MMM yyyy HH:mm:ss zzz"

    for COOKIE in COOKIEs {
        result += "document.COOKIE='\(COOKIE.name)=\(COOKIE.value); domain=\(COOKIE.domain); path=\(COOKIE.path); "
        if let date = COOKIE.expiresDate {
            result += "expires=\(dateFormatter.stringFromDate(date)); "
        }
        if (COOKIE.secure) {
            result += "secure; "
        }
        result += "'; "
    }
    return result
}

#5


8  

Swift 3 update :

斯威夫特3更新:

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
    if let urlRespOnse= navigationResponse.response as? HTTPURLResponse,
       let url = urlResponse.url,
       let allHeaderFields = urlResponse.allHeaderFields as? [String : String] {
       let COOKIEs = HTTPCOOKIE.COOKIEs(withResponseHeaderFields: allHeaderFields, for: url)
       HTTPCOOKIEStorage.shared.setCOOKIEs(COOKIEs , for: urlResponse.url!, mainDocumentURL: nil)
       decisionHandler(.allow)
    }
}

#6


7  

set COOKIE

集饼干

self.webView.evaluateJavascript("document.COOKIE='access_token=your token';domain='your domain';") { (data, error) -> Void in
        self.webView.reload()
}

delete COOKIE

删除饼干

self.webView.evaluateJavascript("document.COOKIE='access_token=';domain='your domain';") { (data, error) -> Void in
        self.webView.reload()
}

#7


6  

In iOS 11, you can manage COOKIE now :), see this session: https://developer.apple.com/videos/play/wwdc2017/220/

在ios11中,您现在可以管理COOKIE:),请参见这个会话:https://developer.apple.com/videos/play/wwdc2017/220/

enter image description here

#8


6  

The COOKIEs must be set on the configuration before the WKWebView is created. Otherwise, even with WKHTTPCOOKIEStore's setCOOKIE completion handler, the COOKIEs won't reliably be synced to the web view. This goes back to this line from the docs on WKWebViewConfiguration

在创建WKWebView之前,必须在配置上设置COOKIE。否则,即使使用WKHTTPCOOKIEStore的setCOOKIE完成处理程序,COOKIE也不能可靠地同步到web视图。这可以追溯到WKWebViewConfiguration上的文档

@NSCopying var configuration: WKWebViewConfiguration { get }

That @NSCopying is somewhat of a deep copy. The implementation is beyond me, but the end result is that unless you set COOKIEs before initializing the webview, you can't count on the COOKIEs being there. This can complicate app architecture because not initializing a view becomes an asynchronous process. You'll end up with something like this

@NSCopying有点像一个深层拷贝。实现超出了我的范围,但是最终的结果是,除非在初始化webview之前设置COOKIE,否则不能指望COOKIE在那里。这可能会使应用程序架构复杂化,因为不初始化视图就会变成一个异步过程。你会得到这样的结果

extension WKWebViewConfiguration {
    /// Async Factory method to acquire WKWebViewConfigurations packaged with system COOKIEs
    static func COOKIEsIncluded(completion: @escaping (WKWebViewConfiguration?) -> Void) {
        let cOnfig= WKWebViewConfiguration()
        guard let COOKIEs = HTTPCOOKIEStorage.shared.COOKIEs else {
            completion(config)
            return
        }
        // Use nonPersistent() or default() depending on if you want COOKIEs persisted to disk
        // and shared between WKWebViews of the same app (default), or not persisted and not shared
        // across WKWebViews in the same app.
        let dataStore = WKWebsiteDataStore.nonPersistent()
        let waitGroup = DispatchGroup()
        for COOKIE in COOKIEs {
            waitGroup.enter()
            dataStore.httpCOOKIEStore.setCOOKIE(COOKIE) { waitGroup.leave() }
        }
        waitGroup.notify(queue: DispatchQueue.main) {
            config.websiteDataStore = dataStore
            completion(config)
        }
    }
}

and then to use it something like

然后使用它

override func loadView() {
    view = UIView()
    WKWebViewConfiguration.COOKIEsIncluded { [weak self] config in
        let webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.load(request)
        self.view = webView
    }
}

The above example defers view creation until the last possible moment, another solution would be to create the config or webview well in advance and handle the asynchronous nature before creation of a view controller.

上面的示例将视图创建延迟到可能的最后一刻,另一种解决方案是提前创建配置或webview,并在创建视图控制器之前处理异步特性。

A final note: once you create this webview, you have set it loose into the wild, you can't add more COOKIEs without using methods described in this answer. You can however use the WKHTTPCOOKIEStoreObserver api to at least observe changes happening to COOKIEs. So if a session COOKIE gets updated in the webview, you can manually update the system's HTTPCOOKIEStorage with this new COOKIE if desired.

最后一个注意事项:一旦你创建了这个webview,你将它释放到野外,你不能添加更多的COOKIE而不使用这个答案中描述的方法。但是,您可以使用WKHTTPCOOKIEStoreObserver api至少观察到COOKIE发生的变化。因此,如果一个会话COOKIE在webview中被更新,你可以用这个新COOKIE手动更新系统的HTTPCOOKIEStorage。

For more on this, skip to 18:00 at this 2017 WWDC Session Custom Web Content Loading. At the beginning of this session, there is a deceptive code sample which omits the fact that the webview should be created in the completion handler.

关于这方面的更多信息,请跳转到2017年WWDC自定义Web内容加载的18:00。在这个会话的开始,有一个欺骗性的代码示例,它忽略了应该在完成处理程序中创建webview的事实。

COOKIEStore.setCOOKIE(COOKIE!) {
    webView.load(loggedInURLRequest)
}

The live demo at 18:00 clarifies this.

18:00现场演示澄清了这一点。

#9


2  

Please find the solution which most likely will work for you out of the box. Basically it's modified and updated for Swift 4 @user3589213's answer.

请找出最适合你的解决方案。基本上,它对Swift 4 @user3589213的答案进行了修改和更新。

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    let headerKeys = navigationAction.request.allHTTPHeaderFields?.keys
    let hasCOOKIEs = headerKeys?.contains("COOKIE") ?? false

    if hasCOOKIEs {
        decisionHandler(.allow)
    } else {
        let COOKIEs = HTTPCOOKIE.requestHeaderFields(with: HTTPCOOKIEStorage.shared.COOKIEs ?? [])

        var headers = navigationAction.request.allHTTPHeaderFields ?? [:]
        headers += COOKIEs

        var req = navigationAction.request
        req.allHTTPHeaderFields = headers

        webView.load(req)

        decisionHandler(.cancel)
    }
}

#10


1  

The better fix for XHR requests is shown here

这里显示了对XHR请求的更好修复

Swift 4 version:

斯威夫特4版本:

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Swift.Void) {
    guard
        let respOnse= navigationResponse.response as? HTTPURLResponse,
        let url = navigationResponse.response.url
    else {
        decisionHandler(.cancel)
        return
    }

    if let headerFields = response.allHeaderFields as? [String: String] {
        let COOKIEs = HTTPCOOKIE.COOKIEs(withResponseHeaderFields: headerFields, for: url)
        COOKIEs.forEach { (COOKIE) in
            HTTPCOOKIEStorage.shared.setCOOKIE(COOKIE)
        }
    }

    decisionHandler(.allow)
}

#11


0  

After looking through various answers here and not having any success, I combed through the WebKit documentation and stumbled upon the requestHeaderFields static method on HTTPCOOKIE, which converts an array of COOKIEs into a format suitable for a header field. Combining this with mattr's insight of updating the URLRequest before loading it with the COOKIE headers got me through the finish line.

在查看了各种各样的答案并没有取得任何成功之后,我梳理了WebKit文档,并在HTTPCOOKIE上发现了requestHeaderFields静态方法,该方法将一组COOKIE转换为适合头字段的格式。结合mattr在使用COOKIE头部加载URLRequest之前更新URLRequest的见解,我完成了这一任务。

Swift 4.1:

var request = URLRequest(url: URL(string: "https://example.com/")!)
let headers = HTTPCOOKIE.requestHeaderFields(with: COOKIEs)
for (name, value) in headers {
    request.addValue(value, forHTTPHeaderField: name)
}

let webView = WKWebView(frame: self.view.frame)
webView.load(request)

To make this even simpler, use an extension:

为了使这更简单,使用扩展:

extension WKWebView {
    func load(_ request: URLRequest, with COOKIEs: [HTTPCOOKIE]) {
        var request = request
        let headers = HTTPCOOKIE.requestHeaderFields(with: COOKIEs)
        for (name, value) in headers {
            request.addValue(value, forHTTPHeaderField: name)
        }

        load(request)
    }
}

Now it just becomes:

现在就变成了:

let request = URLRequest(url: URL(string: "https://example.com/")!)
let webView = WKWebView(frame: self.view.frame)
webView.load(request, with: COOKIEs)

This extension is also available in LionheartExtensions if you just want a drop-in solution. Cheers!

如果您只是想要一个drop-in解决方案,那么在lionheartexties中也可以使用这个扩展。干杯!


推荐阅读
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • position属性absolute与relative的区别和用法详解
    本文详细解读了CSS中的position属性absolute和relative的区别和用法。通过解释绝对定位和相对定位的含义,以及配合TOP、RIGHT、BOTTOM、LEFT进行定位的方式,说明了它们的特性和能够实现的效果。同时指出了在网页居中时使用Absolute可能会出错的原因,即以浏览器左上角为原始点进行定位,不会随着分辨率的变化而变化位置。最后总结了一些使用这两个属性的技巧。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • adfs是什么_培训与开发的概念
    adfs是什么_培训与开发的概念(如您转载本文,必须标明本文作者及出处。如有任何疑问请与我联系me@nap7.com)ADFS相关开发技术的中文资料相对匮乏,之前在弄这个东西的时候 ... [详细]
  • 注意:以下分析都是基于Retrofit2转载请注明出处:http:blog.csdn.netevan_manarticledetails51320637本节是《Retrofit的使 ... [详细]
  • 跨站的艺术XSS Fuzzing 的技巧
    作者|张祖优(Fooying)腾讯云云鼎实验室对于XSS的漏洞挖掘过程,其实就是一个使用Payload不断测试和调整再测试的过程,这个过程我们把它叫做F ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • .NetCoreWebApi生成Swagger接口文档的使用方法
    本文介绍了使用.NetCoreWebApi生成Swagger接口文档的方法,并详细说明了Swagger的定义和功能。通过使用Swagger,可以实现接口和服务的可视化,方便测试人员进行接口测试。同时,还提供了Github链接和具体的步骤,包括创建WebApi工程、引入swagger的包、配置XML文档文件和跨域处理。通过本文,读者可以了解到如何使用Swagger生成接口文档,并加深对Swagger的理解。 ... [详细]
  • 【爬虫】关于企业信用信息公示系统加速乐最新反爬虫机制
    ( ̄▽ ̄)~又得半夜修仙了,作为一个爬虫小白,花了3天时间写好的程序,才跑了一个月目标网站就更新了,是有点悲催,还是要只有一天的时间重构。升级后网站的层次结构并没有太多变化,表面上 ... [详细]
  • Codeigniter3.1.6开启csrf访问被拒绝
    开启CSRF验证,使用表单函数 ... [详细]
  • springboot基于redis配置session共享项目环境配置pom.xml引入依赖application.properties配置Cookie序列化(高版本不需要)测试启 ... [详细]
  • IamgettingaUnicodeerror:UnicodeEncodeError:charmapcodeccantencodecharacteru\xa9in ... [详细]
  • 目前正在做毕业设计,一个关于校园服务的app,我会抽取已完成的相关代码写到文章里。一是为了造福这个曾经帮助过我的社区,二是写文章的同时更能巩固相关知识的记忆。一、前言在爬取教务系统 ... [详细]
author-avatar
秦延深_791
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有