WKWebView 无法使用 NSURLProtocol 拦截请求

针对该问题方案如下:

换用 UIWebView

使用私有 API 进行注册拦截

换用 UIWebView 方案不做赘述,说明下使用私有 API 进行注册拦截的方法 :

// 注册自己的 protocol

[NSURLProtocol registerClass:[CustomProtocol class]];

// 创建 WKWebview

WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc] init];

WKWebView * wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) configuration:config];

[wkWebView loadRequest:webViewReq];

[self.view addSubview:wkWebView];

//注册 scheme

Class cls = NSClassFromString(@"WKBrowsingContextController");

SEL sel = NSSelectorFromString(@"registerSchemeForCustomProtocol:");

if ([cls respondsToSelector:sel]) {

// 通过 http 和 https 的请求,同理可通过其他的 Scheme 但是要满足 ULR Loading System

[cls performSelector:sel withObject:@"http"];

[cls performSelector:sel withObject:@"https"];

}

使用私有 API 的另一风险是兼容性问题,比如上面的 `browsingContextController` 就只能在 iOS 8.4 以后才能用,反注册 scheme 的方法 `unregisterSchemeForCustomProtocol :` 也是在 iOS 8.4 以后才被添加进来的,要支持 iOS 8.0 ~ 8.3 机型的话,只能通过动态生成字符串的方式拿到 `WKBrowsingContextController`,而且还不能反注册,不过这些问题都不大。至于向后兼容,这个也不用太担心,因为 iOS 发布新版本之前都会有开发者预览版的,那个时候再测一下也不迟。对于本文的例子来说,如果将来哪个 iOS 版本移除了这个 API,那很可能是因为官方提供了完整的解决方案,到那时候自然也不需要本文介绍的方法了 。

注意: 避免执行太晚,如果在 `- (void)viewDidLoad` 中注册,可能会因为注册太晚,引发问题。建议在 `+load` 方法中执行 。

然后同样会遇到 [《 HTTPS SNI 业务场景 “ IP直连 ” 方案说明 》](https://help.aliyun.com/document_detail/60147.html) 里提到的各种 NSURLProtocol 相关的问题,可以参照里面的方法解决 。

WebView 中的 Cookie 处理业务场景 IP直连 方案说明

下文将讨论类似这样的问题 :

WKWebView 对于 Cookie 的管理一直是它的短板,那么 iOS11 是否有改进,如果有,如何利用这样的改进 ?

采用 IP 直连方案后,服务端返回的 Cookie 里的 Domain 字段也会使用 IP 。如果 IP 是动态的,就有可能导致一些问题:由于许多 H5 业务都依赖于 Cookie 作登录态校验 ,而 WKWebView 上请求不会自动携带 Cookie 。

WKWebView 使用 NSURLProtocol 拦截请求无法获取 Cookie 信息

iOS 11 推出了新的 API WKHTTPCookieStore 可以用来拦截 WKWebView 的 Cookie 信息

用法示例如下 :

WKHTTPCookieStore *cookieStroe = self.webView.configuration.websiteDataStore.httpCookieStore;

// get cookies

[cookieStroe getAllCookies:^(NSArray * _Nonnull cookies) {

NSLog(@"All cookies %@",cookies);

}];

// set cookie

NSMutableDictionary *dict = [NSMutableDictionary dictionary];

dict[NSHTTPCookieName] = @"userid";

dict[NSHTTPCookieValue] = @"123";

dict[NSHTTPCookieDomain] = @"xxxx.com";

dict[NSHTTPCookiePath] = @"/";

NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:dict];

[cookieStroe setCookie:cookie completionHandler:^{

NSLog(@"set cookie");

}];

// delete cookie

[cookieStroe deleteCookie:cookie completionHandler:^{

NSLog(@"delete cookie");

}];

利用 iOS 11 API WKHTTPCookieStore 解决 WKWebView 首次请求不携带 Cookie 的问题

问题说明:由于许多 H5 业务都依赖于 Cookie 作登录态校验,而 WKWebView 上请求不会自动携带 Cookie 。比如,如果你在 Native 层面做了登陆操作,获取了 Cookie 信息,也使用 NSHTTPCookieStorage 存到了本地,但是使用 WKWebView 打开对应网页时,网页依然处于未登陆状态。如果是登陆也在 WebView 里做的,就不会有这个问题。

iOS 11 的 API 可以解决该问题,只要是存在 WKHTTPCookieStore 里的 cookie,WKWebView 每次请求都会携带,存在 NSHTTPCookieStorage 的 cookie,并不会每次都携带。于是会发生首次 WKWebView 请求不携带 Cookie 的问题。

解决方法:

在执行 -[WKWebView loadReques:] 前将 NSHTTPCookieStorage 中的内容复制到 WKHTTPCookieStore 中,以此来达到 WKWebView Cookie 注入的目的。示例代码如下:

[self copyNSHTTPCookieStorageToWKHTTPCookieStoreWithCompletionHandler:^{

NSURL *url = [NSURL URLWithString:@"https://www.v2ex.com"];

NSURLRequest *request = [NSURLRequest requestWithURL:url];

[_webView loadRequest:request];

}];

- (void)copyNSHTTPCookieStorageToWKHTTPCookieStoreWithCompletionHandler:(nullable void (^)())theCompletionHandler; {

NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];

WKHTTPCookieStore *cookieStroe = self.webView.configuration.websiteDataStore.httpCookieStore;

if (cookies.count == 0) {

!theCompletionHandler ?: theCompletionHandler();

return;

}

for (NSHTTPCookie *cookie in cookies) {

[cookieStroe setCookie:cookie completionHandler:^{

if ([[cookies lastObject] isEqual:cookie]) {

!theCompletionHandler ?: theCompletionHandler();

return;

}

}];

}

}

这个是 iOS 11 的 API ,针对 iOS 11 之前的系统 ,需要另外处理。

作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这有个iOS交流群:642363427,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术,iOS开发者一起交流学习成长!

利用 iOS 11 之前的 API 解决 WKWebView 首次请求不携带 Cookie 的问题

通过让所有 WKWebView 共享同一个 WKProcessPool 实例,可以实现多个 WKWebView 之间共享 Cookie(session Cookie and persistent Cookie)数据。不过 WKWebView WKProcessPool 实例在 app 杀进程重启后会被重置,导致 WKProcessPool 中的 Cookie、session Cookie 数据丢失,目前也无法实现 WKProcessPool 实例本地化保存。可以采取 cookie 放入 Header 的方法来做。

WKWebView * webView = [WKWebView new];

NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://xxx.com/login"]];

[request addValue:@"skey=skeyValue" forHTTPHeaderField:@"Cookie"];

[webView loadRequest:request];

其中对于 skey=skeyValue 这个 cookie 值的获取,也可以统一通过 domain 获取,获取的方法,可以参照下面的工具类:

HTTPDNSCookieManager.h

#ifndef HTTPDNSCookieManager_h

#define HTTPDNSCookieManager_h

// URL匹配Cookie规则

typedef BOOL (^HTTPDNSCookieFilter)(NSHTTPCookie *, NSURL *);

@interface HTTPDNSCookieManager : NSObject

+ (instancetype)sharedInstance;

/**

指定URL匹配Cookie策略

@param filter 匹配器

*/

- (void)setCookieFilter:(HTTPDNSCookieFilter)filter;

/**

处理HTTP Reponse携带的Cookie并存储

@param headerFields HTTP Header Fields

@param URL 根据匹配策略获取查找URL关联的Cookie

@return 返回添加到存储的Cookie

*/

- (NSArray *)handleHeaderFields:(NSDictionary *)headerFields forURL:(NSURL *)URL;

/**

匹配本地Cookie存储,获取对应URL的request cookie字符串

@param URL 根据匹配策略指定查找URL关联的Cookie

@return 返回对应URL的request Cookie字符串

*/

- (NSString *)getRequestCookieHeaderForURL:(NSURL *)URL;

/**

删除存储cookie

@param URL 根据匹配策略查找URL关联的cookie

@return 返回成功删除cookie数

*/

- (NSInteger)deleteCookieForURL:(NSURL *)URL;

@end

#endif /* HTTPDNSCookieManager_h */

HTTPDNSCookieManager.m

#import

#import "HTTPDNSCookieManager.h"

@implementation HTTPDNSCookieManager

{

HTTPDNSCookieFilter cookieFilter;

}

- (instancetype)init {

if (self = [super init]) {

/**

此处设置的Cookie和URL匹配策略比较简单,检查URL.host是否包含Cookie的domain字段

通过调用setCookieFilter接口设定Cookie匹配策略,

比如可以设定Cookie的domain字段和URL.host的后缀匹配 | URL是否符合Cookie的path设定

细节匹配规则可参考RFC 2965 3.3节

*/

cookieFilter = ^BOOL(NSHTTPCookie *cookie, NSURL *URL) {

if ([URL.host containsString:cookie.domain]) {

return YES;

}

return NO;

};

}

return self;

}

+ (instancetype)sharedInstance {

static id singletonInstance = nil;

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

if (!singletonInstance) {

singletonInstance = [[super allocWithZone:NULL] init];

}

});

return singletonInstance;

}

+ (id)allocWithZone:(struct _NSZone *)zone {

return [self sharedInstance];

}

- (id)copyWithZone:(struct _NSZone *)zone {

return self;

}

- (void)setCookieFilter:(HTTPDNSCookieFilter)filter {

if (filter != nil) {

cookieFilter = filter;

}

}

- (NSArray *)handleHeaderFields:(NSDictionary *)headerFields forURL:(NSURL *)URL {

NSArray *cookieArray = [NSHTTPCookie cookiesWithResponseHeaderFields:headerFields forURL:URL];

if (cookieArray != nil) {

NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

for (NSHTTPCookie *cookie in cookieArray) {

if (cookieFilter(cookie, URL)) {

NSLog(@"Add a cookie: %@", cookie);

[cookieStorage setCookie:cookie];

}

}

}

return cookieArray;

}

- (NSString *)getRequestCookieHeaderForURL:(NSURL *)URL {

NSArray *cookieArray = [self searchAppropriateCookies:URL];

if (cookieArray != nil && cookieArray.count > 0) {

NSDictionary *cookieDic = [NSHTTPCookie requestHeaderFieldsWithCookies:cookieArray];

if ([cookieDic objectForKey:@"Cookie"]) {

return cookieDic[@"Cookie"];

}

}

return nil;

}

- (NSArray *)searchAppropriateCookies:(NSURL *)URL {

NSMutableArray *cookieArray = [NSMutableArray array];

NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

for (NSHTTPCookie *cookie in [cookieStorage cookies]) {

if (cookieFilter(cookie, URL)) {

NSLog(@"Search an appropriate cookie: %@", cookie);

[cookieArray addObject:cookie];

}

}

return cookieArray;

}

- (NSInteger)deleteCookieForURL:(NSURL *)URL {

int delCount = 0;

NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

for (NSHTTPCookie *cookie in [cookieStorage cookies]) {

if (cookieFilter(cookie, URL)) {

NSLog(@"Delete a cookie: %@", cookie);

[cookieStorage deleteCookie:cookie];

delCount++;

}

}

return delCount;

}

@end

使用方法示例:

发送请求

WKWebView * webView = [WKWebView new];

NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://xxx.com/login"]];

NSString *value = [[HTTPDNSCookieManager sharedInstance] getRequestCookieHeaderForURL:url];

[request setValue:value forHTTPHeaderField:@"Cookie"];

[webView loadRequest:request];

接收处理请求:

NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

if (!error) {

NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

// 解析 HTTP Response Header,存储cookie

[[HTTPDNSCookieManager sharedInstance] handleHeaderFields:[httpResponse allHeaderFields] forURL:url];

}

}];

[task resume];

通过 document.cookie 设置 Cookie 解决后续页面(同域)Ajax、iframe 请求的 Cookie 问题;

WKUserContentController* userContentController = [WKUserContentController new];

WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource: @"document.cookie = 'skey=skeyValue';" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];

[userContentController addUserScript:cookieScript];

Cookie包含动态 IP 导致登陆失效问题

关于 COOKIE 失效的问题,假如客户端登录 session 存在 COOKIE,此时这个域名配置了多个 IP,使用域名访问会读对应域名的 COOKIE,使用IP访问则去读对应 IP 的 COOKIE,假如前后两次使用同一个域名配置的不同 IP 访问,会导致 COOKIE 的登录 session 失效,

如果 APP 里面的 webview 页面需要用到系统 COOKIE 存的登录 session,之前 APP 所有本地网络请求使用域名访问,是可以共用 COOKIE 的登录 session 的,但现在本地网络请求使用 httpdns后改用 IP 访问,导致还使用域名访问的 webview 读不到系统 COOKIE 存的登录 session 了(系统 COOKIE 对应 IP 了)。IP 直连后,服务端返回 Cookie 包含动态 IP 导致登陆失效。

使用 IP 访问后,服务端返回的 cookie 也是 IP。导致可能使用对应的域名访问,无法使用本地 cookie,或者使用隶属于同一个域名的不同 IP 去访问,cookie 也对不上,导致登陆失效 。

我这边的思路是这样的,

应该得干预 cookie 的存储,基于域名。

根源上,api 域名返回单 IP

第二种思路将失去 DNS 调度特性,故不考虑。第一种思路更为可行。

基于 iOS11 API WKHTTPCookieStore 来解决 WKWebView 的 Cookie 管理问题

当每次服务端返回cookie后,在存储前都进行下改造,使用域名替换下IP。之后虽然每次网络请求都是使用IP访问,但是host我们都手动改为了域名,这样本地存储的 cookie 也就能对得上了。

代码演示:

在网络请求成功后,或者加载网页成功后,主动将本地的 domain 字段为 IP 的 Cookie 替换 IP 为 host 域名地址。

- (void)updateWKHTTPCookieStoreDomainFromIP:(NSString *)IP toHost:(NSString *)host {

WKHTTPCookieStore *cookieStroe = self.webView.configuration.websiteDataStore.httpCookieStore;

[cookieStroe getAllCookies:^(NSArray * _Nonnull cookies) {

[[cookies copy] enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull cookie, NSUInteger idx, BOOL * _Nonnull stop) {

if ([cookie.domain isEqualToString:IP]) {

NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:cookie.properties];

dict[NSHTTPCookieDomain] = host;

NSHTTPCookie *newCookie = [NSHTTPCookie cookieWithProperties:[dict copy]];

[cookieStroe setCookie:newCookie completionHandler:^{

[self logCookies];

[cookieStroe deleteCookie:cookie

completionHandler:^{

[self logCookies];

}];

}];

}

}];

}];

}

iOS 11 中也提供了对应的 API 供我们来处理替换 Cookie 的时机,那就是下面的 API:

@protocol WKHTTPCookieStoreObserver

@optional

- (void)cookiesDidChangeInCookieStore:(WKHTTPCookieStore *)cookieStore;

@end

//WKHTTPCookieStore

/*! @abstract Adds a WKHTTPCookieStoreObserver object with the cookie store.

@param observer The observer object to add.

@discussion The observer is not retained by the receiver. It is your responsibility

to unregister the observer before it becomes invalid.

*/

- (void)addObserver:(id)observer;

/*! @abstract Removes a WKHTTPCookieStoreObserver object from the cookie store.

@param observer The observer to remove.

*/

- (void)removeObserver:(id)observer;

用法如下:

@interface WebViewController ()

- (void)viewDidLoad {

[super viewDidLoad];

[NSURLProtocol registerClass:[WebViewURLProtocol class]];

NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

[cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];

WKHTTPCookieStore *cookieStroe = self.webView.configuration.websiteDataStore.httpCookieStore;

[cookieStroe addObserver:self];

[self.view addSubview:self.webView];

//... ...

}

#pragma mark -

#pragma mark - WKHTTPCookieStoreObserver Delegate Method

- (void)cookiesDidChangeInCookieStore:(WKHTTPCookieStore *)cookieStore {

[self updateWKHTTPCookieStoreDomainFromIP:CYLIP toHost:CYLHOST];

}

-updateWKHTTPCookieStoreDomainFromIP 方法的实现,在上文已经给出。

这个方案需要客户端维护一个IP —> HOST的映射关系,需要能从 IP 反向查找到 HOST,这个维护成本还时挺高的。下面介绍下,更通用的方法,也是iOS11 之前的处理方法:

iOS 11 之前的处理方法:NSURLProtocal 拦截后,手动管理 Cookie 的存储:

步骤:做 IP 替换时将原始 URL 保存到 Header 中

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {

NSMutableURLRequest *mutableReq = [request mutableCopy];

NSString *originalUrl = mutableReq.URL.absoluteString;

NSURL *url = [NSURL URLWithString:originalUrl];

// 异步接口获取IP地址

NSString *ip = [[HttpDnsService sharedInstance] getIpByHostAsync:url.host];

if (ip) {

NSRange hostFirstRange = [originalUrl rangeOfString:url.host];

if (NSNotFound != hostFirstRange.location) {

NSString *newUrl = [originalUrl stringByReplacingCharactersInRange:hostFirstRange withString:ip];

mutableReq.URL = [NSURL URLWithString:newUrl];

[mutableReq setValue:url.host forHTTPHeaderField:@"host"];

// 添加originalUrl保存原始URL

[mutableReq addValue:originalUrl forHTTPHeaderField:@"originalUrl"];

}

}

NSURLRequest *postRequestIncludeBody = [mutableReq cyl_getPostRequestIncludeBody];

return postRequestIncludeBody;

}

然后获取到数据后,手动管理 Cookie :

- (void)handleCookiesFromResponse:(NSURLResponse *)response {

NSString *originalURLString = [self.request valueForHTTPHeaderField:@"originalUrl"];

if ([response isKindOfClass:[NSHTTPURLResponse class]]) {

NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

NSDictionary *allHeaderFields = httpResponse.allHeaderFields;

if (originalURLString && originalURLString.length > 0) {

NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:allHeaderFields forURL: [[NSURL alloc] initWithString:originalURLString]];

if (cookies && cookies.count > 0) {

NSURL *originalURL = [NSURL URLWithString:originalURLString];

[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:originalURL mainDocumentURL:nil];

}

}

}

}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)newRequest completionHandler:(void (^)(NSURLRequest *))completionHandler {

NSString *location = response.allHeaderFields[@"Location"];

NSURL *url = [[NSURL alloc] initWithString:location];

NSMutableURLRequest *mRequest = [newRequest mutableCopy];

mRequest.URL = url;

if (location && location.length > 0) {

if ([[newRequest.HTTPMethod lowercaseString] isEqualToString:@"post"]) {

// POST重定向为GET

mRequest.HTTPMethod = @"GET";

mRequest.HTTPBody = nil;

}

[mRequest setValue:nil forHTTPHeaderField:@"host"];

// 在这里为 request 添加 cookie 信息。

[self handleCookiesFromResponse:response];

[XXXURLProtocol removePropertyForKey:XXXURLProtocolHandledKey inRequest:mRequest];

completionHandler(mRequest);

} else{

completionHandler(mRequest);

}

}

发送请求前,向请求中添加Cookie信息:

+ (void)handleCookieWithRequest:(NSMutableURLRequest *)request {

NSString* originalURLString = [request valueForHTTPHeaderField:@"originalUrl"];

if (!originalURLString || originalURLString.length == 0) {

return;

}

NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];

if (cookies && cookies.count >0) {

NSDictionary *cookieHeaders = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];

NSString *cookieString = [cookieHeaders objectForKey:@"Cookie"];

[request addValue:cookieString forHTTPHeaderField:@"Cookie"];

}

}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {

NSMutableURLRequest *mutableReq = [request mutableCopy];

//...

[self handleCookieWithRequest:mutableReq];

return [mutableReq copy];

}

推荐

ip访问 webstorem_常见问题-iOS WebView IP直连 如何处理 Cookie相关推荐

  1. Oracle11g限制ip访问数据库,ORACLE 限制特定IP访问数据库

    (1)在9i中真正起作用的是sqlnet.ora文件,我们修改sqlnet.ora其实是最好最快的方法. 在sqlnet.ora中增加如下部分 ---------------------------- ...

  2. centos7 禁止ip访问_centos7 防火墙操作 屏蔽ip

    这里用到的是iptables命令 iptables -I INPUT -s 124.115.0.199 -j DROP 是屏蔽124.115.0.199这个IP iptables -I INPUT - ...

  3. php限制ip访问次数 并发_nginx限制ip请求次数 以及并发次数

    如何设置能限制某个IP某一时间段的访问次数是一个让人头疼的问题,特别面对恶意的ddos攻击的时候.其中CC攻击(Challenge Collapsar)是DDOS(分布式拒绝服务)的一种,也是一种常见 ...

  4. 服务器禁止用ip访问站点,windows服务器禁止ip访问方法介绍

    下边是方法 控制面板-管理工具-本地安全策略  或者命令  gpedit.msc 选择创建 IP 安全策略 点选下一步 我们就是要禁止他,不和他说话,那么,取消勾选 直接按完成.那个勾选是默认的 注意 ...

  5. python使用代理ip访问网站_python使用代理ip访问网站的实例

    实例如下所示: # -*- coding: UTF-8 -*- from urllib import request if __name__ == "__main__": #访问网 ...

  6. ip访问次数统计 nginx_PHP实现IP访问限制及提交次数的方法详解

    一.原理 提交次数是肯定要往数据库里写次数这个数据的,比如用户登陆,当用户出错时就忘数据库写入出错次数1,并且出错时间,再出错写2,当满比如5次时提示不允许再登陆,请明天再试,然后用DateDiff计 ...

  7. 网站限制某些ip访问,仅允许某些ip…

    代码: function getIP() { return isset($_SERVER["HTTP_X_FORWARDED_FOR"])?$_SERVER["HTTP_ ...

  8. Linux上基于IP访问网站、基于同一IP不同端口访问网站、基于DNS域名访问网站、将不同域名解析到同一IP不同端口

    本文基于Linux上CentOS 7版本配合httpd服务.nginx进行配置演示 一.基于IP搭建web服务器 1.为虚拟机网卡新添加一个ip地址并重启网卡 2. 新建配置目录并写入内容 3.编辑配 ...

  9. ORACLE 限制特定IP访问数据库 访问白名单

    限制指定机器IP访问oracle数据库 通过使用数据库服务器端的sqlnet.ora文件可以实现禁止指定IP主机访问数据库的功能,这对于提升数据库的安全性有很大的帮助,与此同时,这个技术为我们管理和约 ...

最新文章

  1. malloc为什么会报错:memory corruption
  2. MySQL安装后第一次修改密码
  3. leetcode c程序总提示主函数_Matlab系列之函数嵌套
  4. 散列查找 散列表(哈希表)
  5. MySQL null与not null和null与空值‘‘的区别
  6. 从学校到现在的一个总结
  7. 12c r2单实例 静默安装软件
  8. 我应关注的AEC算法细分
  9. SpringCloud Eureka 高可用
  10. 10.Configure One-to-Many(配置一对多关系)【Code-First系列】
  11. iis 访问网站需要进行身份验证
  12. python爬虫下载文件到指定文件夹_python爬虫: 从 指定路径 爬取 文件
  13. 计算机省vb二级试题,江苏省计算机二级VB试题及答案
  14. 入门DP教程(超详细)
  15. 三级网络技术综合、应用题(2019、3)
  16. html中点击按钮闪现,vue使用v-if v-show页面闪烁,div闪现的解决方法
  17. maven(视频学习)
  18. 六年级上册计算机期末试题及答案,小学六年级上册数学期末检测试题
  19. QT使用openGL绘制一个三角形
  20. 阴天(唐伯虎点秋香版)2铃声 阴天(唐伯虎点秋香版)2手机铃声免...

热门文章

  1. python输入hello输出olleh_leetcode上的python练习(6)
  2. Spring事务回滚和异常类
  3. SpringMvc接收日期参数
  4. JUC锁-Condition(三)
  5. C++ deque 底层原理及 queue、stack 容器的使用详解
  6. 14.refresh操作
  7. 什么是51%算力攻击?——区块链系列学习笔记
  8. idea点击表单按钮不做post反应
  9. Apache服务日志分割(rotatelogs、cronolog)
  10. [java][工具类][Arrays]