使用windows验证(Using Windows Authentication)

在软件术语里面,验证的意思是测定身份。这个跟授权是完全分开的,授权是让合适的人做合适的事情,授权通常在验证之后发生。ASP.NET的验证功能也紧紧围绕识别访问者的身份并且设置决定实际的访问者能够做什么的安全上下文(security context)。最简单的验证方式就是把这个任务委托给IIS(这通常适合内部系统)。在配置文件里启用Windows身份验证,如果我们使用的Intranet应用程序模版,默认会使用这个配置。如下:
<configuration>
    <system.web>
        <authentication mode="Windows" />
    </system.web>
</configuration>
使用windows验证,ASP.NET依赖于IIS来验证用户的请求,并且有如下模式:
①匿名验证:允许任何用户访问,IIS7默认启用
②基本验证:需要用户提供一个经过验证的用户名和密码,验证标识作为文本会从浏览器发送到服务器,这种模式仅仅应该在SSL连接的基础上使用
③摘要验证:需要用户名和密码,验证标识会被加密为hash代码发送到服务器。安全性比基本验证更高,并且需要服务器是一个域控制器。
④windows验证:通过windows域透明地建立用户的身份,不需要提供其他的认证。在企业内部局域网使用广泛,不适合面向Internet的应用。
可以在IIS管理器里面设置验证模式,如下:


如果我们想让所有的请求都经过验证,需要我们禁用匿名验证功能。如果只是部分限制,那么可以启用匿名验证并对actions和controllers使用验证过滤器。在局域网部署程序,那么使用windows验证是非常有用的。如果用户是来自Internet,应用程序倾向于依赖表单验证。

使用表单验证(Using Forms Authentication)

表单验证非常适合面向Internet网的程序,当然建立表单验证也会比windows验证更加复杂,一旦设置都完毕,那么比windows验证将会更加灵活。表单验证的安全性依赖于一加密的cookie——.ASPXAUTH。这个cookie内容类似于:
9CC50274C662470986ADD690704BF652F4DFFC3035FC19013726A22F794B3558778B12F799852B2E84
D34D79C0A09DA258000762779AF9FCA3AD4B78661800B4119DD72A8A7000935AAF7E309CD81F28
用FormsAuthentication.Decrypt对其进行解密,可以得到一个FormsAuthenticationTicket对象并且具有如下属性:


其中里面一个关键的属性就是Name,这个跟用户请求的相关联的身份标识。系统的安全性的保证来自于cookie数据的机密和使用服务器的machine keys的签名。这些是由IIS自动生成的,并且如果没有这些keys,包含在cookie里的验证信息是不能被读取和修改的。

Tip:当我们把使用了表单验证的程序部署到服务器集群时,必须保证请求总是返回生成cookie的服务器或保证所有的服务器具有相同的machine keys。这些Keys可以使用IIS管理器里面的machine keys选项来生成和配置。

 

建立表单验证(Setting Up Forms Authentication)

当我们使用互联网应用程序模版创建一个MVC程序时,默认启用了表单身份验证,相关的配置如下:
  <authentication mode="Forms">
    <forms loginUrl="~/Account/LogOn" timeout="2880" />
  </authentication>
这个配置能够适合大多数程序,当然也可以定义更多的属性来控制,这些属性如下:

属性名 默认值 描述
name .ASPXAUTH cookie名
timeout 30分钟 超时时间
slidingExpiration true 滑动过去时间
domain None 跨子域共享(www.example.com和a.example.com)
path / 设置验证cookie发送到指定的URL,这个让我们可以在同一个域中寄宿多个应用程序而不会暴露彼此的验证cookie
loginUrl /login.aspx 如果表单需要用户登录,重定向到指定的登录页面
cookieless UserDeviceProfile 启用无cookie验证
requireSSL false 设置为true会建议浏览器仅仅在使用SSL加密的请求中传递cookie

在web.config文件启用表单验证,当没有经过验证的用户访问到任何标记了[Authorize]的controller和action时会跳转到登录页。

 

使用无cookie的表单验证(Using Cookieless Forms Authentication)

表单验证支持无cookie模式,这种情况下验证的票据存放在URL里,数据仍然是签名和加密的,但是会作为URL的一部分发送到服务器。只要每一个请求包含了验证数据,那么用户接收到同样应用程序的体验跟启用了cookie是一样的。启用无cookie验证的配置如下:
<authentication mode="Forms">
  <forms loginUrl="~/Account/LogOn" timeout="2880" cookieless="UseUri">
  </forms>
</authentication>

当用户登录时,他们会被重定向到一个像如下的URL:
/(F(nMD9DiT464AxL7nlQITYUTT05ECNIJ1EGwN4CaAKKze-9ZJq1QTOK0vhXTx0fWRjAJdgSYojOYyhDil
HN4SRb4fgGVcn_fnZU0x55I3_Jes1))/Home/ShowPrivateInformation
仔细观察会发现,URL遵循这样的模式:/(F(authenticationData))/normalUrl
我们不用特别的步骤和配置,路由系统会仔细转换这些URL以至于我们的路由配置能够适应任何改变并且HTML辅助方法会自动生成这种类型的URL。不推荐使用无cookie的验证,因为这种验证非常脆弱,如果有一个链接没有包含验证信息,那么用户马上就被注销了。无cookie验证也是不安全的,任何一个人复制你的URL并共享给其他人,那么第一个用户的session将会被劫持。而且,如果我们依赖了从第三方服务器获取的内容,那么我们的验证数据会通过浏览器的引用头(Referer header)发送给第三方。最后,这个URL看起非常丑陋,没有可读性和吸引力。

使用Membership,Roles和Profiles

在SportsStroe项目里面,我们在Web.config文件里面存储了用户的证书信息,对于小的程序和用户不会经常改变并且用户数量很小的情况下可以这样使用。ASP.NET提供了一套标准的用户账户系统来支持常用的用户账户管理任务,包含注册,密码管理,个性设置。具有三个关键的功能区域:
Membership:注册用户账户并访问账户详情和授权证书
Roles:把用户放入组里面,对身份验证的典型应用
Profiles:存储每一个用户的基础数据
ASP.NET对上面的三个区域提供了标准的实现,但是我们也可以跟自定义的实现混合使用,通过一个providers系统就可以实现。内置的providers能够以不同的方式存储数据,包括SQL Server和活动目录。

建立和使用Membership
ASP.NET里面已经有了SqlMembershipProvider和ActiveDirectoryMembershipProvider两个提供者。下面会介绍如何最常规的使用:

建立SqlMembershipProvider

当使用互联网应用程序模版创建一个MVC程序时,默认配置了SqlMembershipProvider。配置的Web.config如下:

View Code

<configuration> <connectionStrings> <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI; AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" /> </connectionStrings> ... <system.web> <membership> <providers> <clear/> <add name="AspNetSqlMembershipProvider"  type="System.Web.Security.SqlMembershipProvider"  connectionStringName="ApplicationServices" enablePasswordRetrieval="false"  enablePasswordReset="true"  requiresQuestionAndAnswer="false"  requiresUniqueEmail="false" maxInvalidPasswordAttempts="5"  minRequiredPasswordLength="6"  minRequiredNonalphanumericCharacters="0"passwordAttemptWindow="10" applicationName="/" /> </providers> </membership>
</system.web>
</configuration>

SQL Server Express版本的数据库支持一个user实例的数据库,这些数据库是不用在之前配置就可以使用的。付费版的SQL Server不支持用户实例数据库,需要在使用之前准备好该数据库。安装方法:运行aspnet_regsql.exe。安装完了可以去SQL Server management studio里面查看下。

管理Membership

Membership API包含对注册用户的管理方法:添加和移除账户,重置密码等等。对于一些简单的情形,完全可以使用站点管理工具(VS里面有对应的按钮)。如下:


一旦部署了应用程序,我们能够通过IIS .NET用户选项来管理应用程序的用户。使用.NET User选项时,IIS管理工具读取Web.config文件并且视图确保membership提供者是值得信任的。不太走运的是,IIS管理工具是基于.NET2.0并且尚未更新到支持ASP.NET4.当前的IIS版本,微软对使用.NET4的程序禁用了.NET Users选项。下面看看示例的配置文件:

View Code

<?xml version="1.0" encoding="UTF-8"?> <configuration> <connectionStrings> <add name="ApplicationServices" connectionString="data Source=TITAN\SQLEXPRESS; Initial Catalog=aspnetdb; Persist Security Info=True; User ID=adam;Password=adam" providerName="System.Data.SqlClient" /> </connectionStrings> <system.web> <authentication mode="Forms"> <forms loginUrl="~/Account/LogOn" timeout="2880" /> </authentication> <membership> <providers> <remove name="AspNetSqlMembershipProvider"/> <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral,                    PublicKeyToken=b03f5f7f11d50a3a"     connectionStringName="ApplicationServices" applicationName="/" /> </providers> </membership> </system.web>
</configuration> 

这是一个精简过的Web.config文件,只包含两个配置节:connection string和membership database,使用时编辑适合自己的环境。

创建一个自定义的Membership提供者

通过从抽象类MembershipProvider派生可以创建自定义的membership提供者,如下所示:

View Code

using System;
using System.Web.Security;
using System.Collections.Generic; namespace MvcApp.Infrastructure { public class SiteMember { public string UserName { get; set; } public string Password { get; set; } } public class CustomMembershipProvider : MembershipProvider { private static List<SiteMember> Members = new List<SiteMember> { new SiteMember { UserName = "adam", Password = "secret" }, new SiteMember { UserName = "steve", Password = "shhhh" } }; public override bool ValidateUser(string username, string password) { return Members.Exists(m => m.UserName == username && m.Password == password); } ... ... }
}

上面的Provider使用一个静态的用户和密码列表来执行验证,为了简单说明原理,这里忽略了除ValidateUser之外的其他的方法。接着在配置文件注册自定义的Provider:

View Code

<configuration>     <system.web> <authentication mode="Forms"> <forms loginUrl="~/Account/LogOn" timeout="2880" /> </authentication> <membership defaultProvider="MyMembershipProvider"> <providers> <clear/> <add name="MyMembershipProvider" type="MvcApp.Infrastructure.CustomMembershipProvider"/> </providers> </membership> </system.web>
</configuration> 

下面截取一个在SportsStore里面使用的例子:

View Code

using System.Web.Security;
using SportsStore.WebUI.Infrastructure.Abstract; namespace SportsStore.WebUI.Infrastructure.Concrete { public class FormsAuthProvider : IAuthProvider { public bool Authenticate(string username, string password) { bool result = Membership.ValidateUser(username, password); if (result) { FormsAuthentication.SetAuthCookie(username, false); }             return result; } }
} 

建立并使用角色

前面介绍了验证,还有另外一个常见的安全需求就是授权——决定用户在验证之后能够做什么。ASP.NET使用基于角色的授权机制,这意味着actions是限制在角色里面的,属于角色的用户能够执行相应的action方法。角色通过唯一的字符串值来表示,例如可以定义如下三个角色:ApprovedMember  CommentsModerator  SiteAdministrator。每一个角色都是完全独立的,没有层级关系。ASP.NET平台期望我们通过provider模型来使用角色,提供了常用的API。当然也可以自定义:

建立SqlRoleProvider

SqlRoleProvider类是对SqlMembershipProvider的补足,使用了同样的数据库。使用互联网应用程序模版创建MVC程序,VS会自动添加相应的元素来建立SqlRoleProvider,如下:

View Code

<configuration> <system.web> <roleManager enabled="false"> <providers> <clear/> <add name="AspNetSqlRoleProvider"  type="System.Web.Security.SqlRoleProvider"  connectionStringName="ApplicationServices"  applicationName="/" /> <add name="AspNetWindowsTokenRoleProvider"  type="System.Web.Security.WindowsTokenRoleProvider"  applicationName="/" /> </providers> </roleManager>
</configuration> 

两个Role Provider注册了,默认都没有启用。要建立SqlRoleProvider必须修改roleManager元素
如:<roleManager enabled="true" defaultProvider="AspNetSqlRoleProvider">

管理Roles

可以使用管理members的方法管理roles,可以使用VS里面的ASP.NET图形化的配置工具来操作。下面介绍创建自定义的Roles Provider:

View Code

using System;
using System.Web.Security; namespace MvcApp.Infrastructure { public class CustomRoleProvider : RoleProvider { public override string[] GetRolesForUser(string username) { if (username == "adam") { return new string[] { "CommentsModerator", "SiteAdministrator" }; } else if (username == "steve") { return new string[] { "ApprovedUser", "CommentsModerator" }; } else { return new string[] { }; } } ...... }
} 

通过从RoleProvider派生来定义自己的提供者,我只需要实现GetRolesForUser方法就可以使用了。同样,创建以后需要注册:

View Code

<configuration> <system.web> <authentication mode="Forms"> <forms loginUrl="~/Account/LogOn" timeout="2880" /> </authentication> <membership defaultProvider="MyMembershipProvider"> <providers> <clear/> <add name="MyMembershipProvider" type="MvcApp.Infrastructure.CustomMembershipProvider"/> </providers> </membership> <roleManager enabled="true" defaultProvider="MyRoleProvider">       <providers> <clear/> <add name="MyRoleProvider" type="MvcApp.Infrastructure.CustomRoleProvider"/> </providers>         </roleManager> </system.web>
</configuration> 

建立并使用Profiles

Membership记录我们的用户,roles记录允许用户做什么操作。如果我们想记录用户个性化的一些数据,如会员积分等等信息。那么通常可以使用Profiles,这对于使用SqlMembershipProvider的小应用程序来说是一个非常有吸引力的功能。

建立SqlProfileProvider

使用互联网应用程序模版创建一个新的MVC程序,包含在Web.config里面的元素创建SqlProfileProvider。如下:

View Code

<configuration> <system.web> <profile> <providers> <clear/> <add name="AspNetSqlProfileProvider"  type="System.Web.Profile.SqlProfileProvider"  connectionStringName="ApplicationServices"  applicationName="/" /> </providers> </profile> </system.web>
</configuration> 

配置/读/写Profile数据

在使用Profile之前,我们必须定义Profile的数据结构,可以在Web.config的profile节里面添加属性元素如下:

View Code

<profile> <providers> <clear/> <add name="AspNetSqlProfileProvider"  type="System.Web.Profile.SqlProfileProvider"  connectionStringName="ApplicationServices"  applicationName="/" /> </providers> <properties> <add name="Name" type="String"/> <group name="Address"> <add name="Street" type="String"/> <add name="City" type="String"/> <add name="ZipCode" type="String"/> <add name="State" type="String"/> </group> </properties>
</profile> 

上面定义的属性都是String类型的,但是Profile支持任何能够序列化的.NET类型。在我们使用Web Forms的时候,通过跟profiles属性一致的代理对象来访问profile数据。这个在MVC里是不可行的,但是我们可以使用HttpContext.Profile属性来访问。如:

View Code

public ActionResult Index() { ViewBag.Name = HttpContext.Profile["Name"]; ViewBag.City = HttpContext.Profile.GetProfileGroup("Address")["City"]; return View();
} [HttpPost]
public ViewResult Index(string name, string city) { HttpContext.Profile["Name"] = name; HttpContext.Profile.GetProfileGroup("Address")["City"] = city; return View();
} 

ASP.NET框架在我们第一次访问profile数据时,使用profile提供者载入用户的profile属性并且在请求结束时通过profile提供者写回,我们不用显示的保存,这个是自动完成的。

启用匿名的Profiles

默认情况下,profile数据只对经过验证的用户可用,没有登录的用户访问时会抛异常。可以通过启用对你们profile的支持来解决:

View Code

<configuration> <system.web> <anonymousIdentification enabled="true"/> <profile> <providers> <clear/> <add name="AspNetSqlProfileProvider"  type="System.Web.Profile.SqlProfileProvider"  connectionStringName="ApplicationServices"  applicationName="/" /> </providers> <properties> <add name="Name" type="String" allowAnonymous="true"/> <group name="Address"> <add name="Street" type="String"/> <add name="City" type="String" allowAnonymous="true"/> <add name="ZipCode" type="String"/> <add name="State" type="String"/> </group> </properties> </profile> </system.web>
</configuration> 

当匿名的身份标识启用时,ASP.NET框架将会通过一个.ASPXANONYMOUS的cookie来记录你们用户,并且cookie的过期时间是10000分钟(70天左右)。启用了匿名profile以后,没有验证的用户也可以读写profile数据,没一个没有验证的用户会自动为他们创建一个账户并保存在profile数据库里面。

创建自定义的Profile提供者(Profile Provider)

通过从ProfileProvider派生来创建自定义的profile provider。如下:

View Code

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web.Profile; namespace MvcApp.Infrastructure { public class CustomProfileProvider : ProfileProvider { private IDictionary<string, IDictionary<string, object>> data =  new Dictionary<string, IDictionary<string, object>>(); public override SettingsPropertyValueCollection GetPropertyValues( SettingsContext context, SettingsPropertyCollection collection) { SettingsPropertyValueCollection result = new SettingsPropertyValueCollection(); IDictionary<string, object> userData; bool userDataExists  = data.TryGetValue((string)context["UserName"], out userData); foreach (SettingsProperty prop in collection) { SettingsPropertyValue spv = new SettingsPropertyValue(prop); if (userDataExists) { spv.PropertyValue = userData[prop.Name]; } result.Add(spv); } return result; } public override void SetPropertyValues(SettingsContext context,  SettingsPropertyValueCollection collection) { string userName = (string)context["UserName"]; if (!string.IsNullOrEmpty(userName)) { data[userName] = collection .Cast<SettingsPropertyValue>() .ToDictionary(x => x.Name, x => x.PropertyValue);             } } ...... }
} 

上面的provider非常简单,仅仅将数据存储在内存。接着需要注册:

View Code

<configuration> <connectionStrings> <add name="ApplicationServices" connectionString="data Source=TITAN\SQLEXPRESS; Initial Catalog=aspnetdb; Persist Security Info=True; User ID=adam;Password=adam" providerName="System.Data.SqlClient" /> </connectionStrings> <system.web> <authentication mode="Forms"> <forms loginUrl="~/Account/LogOn" timeout="2880" /> </authentication> <membership defaultProvider="MyMembershipProvider"> <providers> <clear/> <add name="MyMembershipProvider" type="MvcApp.Infrastructure.CustomMembershipProvider"/> </providers> </membership> <roleManager enabled="true" defaultProvider="MyRoleProvider"> <providers> <clear/> <add name="MyRoleProvider" type="MvcApp.Infrastructure.CustomRoleProvider"/> </providers> </roleManager> <profile enabled="true" defaultProvider="MyProfileProvider"> <providers> <clear/> <add name="MyProfileProvider"  type="MvcApp.Infrastructure.CustomProfileProvider"  />
</providers> <properties> <add name="Name" type="String"/> <group name="Address"> <add name="Street" type="String"/> <add name="City" type="String"/> <add name="ZipCode" type="String"/> <add name="State" type="String"/> </group> </properties> </profile>     </system.web>
</configuration> 

 

为什么不应该使用基于URL的授权(Why You Shouldn’t Use URL-Based Authorization)

ASP.NET曾经依靠匹配URL到应用程序的目录结构来实现授权,这样的做法非常多以至于在URL模式中定义授权规则有非常重要的意义。很多Webform的程序,例如把所有管理员的aspx页面放在一个Admin的文件夹下,这意味着我们可以使用基于URL的授权来限制登录的用户对/Admin/*的访问。这种方式对MVC框架是没有用的,因为路由系统的存在打破了URL跟文件系统之间的联系。正确做法是在controller上使用Authorize过滤器(前面的章节有介绍)

 

使用IP地址和域名限制访问(Restricting Access Using IP Addresses and Domains)

首先介绍下这么做的风险:
这种方式应该谨慎使用,有很多潜在的风险。首先这是基于URL的授权,并且不能很完善的跟MVC的路由系统相适应。其次,用这种方式限制访问没有考虑用户怎样跟我们应用程序的可能的交互。举一个例子,亚当今天早上在家第一次上网,后来他在咖啡店连接上网,在朋友家上网,在另一个朋友的办公室上网,最后回到家里上网。在上面的情形里有些是通过VPN连接的,有些是直接连的网。基于用户从哪连接网络来限制访问很容易建立,但是要想得到正确的判断很困难。下面的Web.config使用了IP地址和域名限制来建立:

View Code

<configuration> <location path="Home"> <system.webServer> <security> <ipSecurity enableReverseDns="true"> <clear/> <add ipAddress="192.188.100.1"/> <add ipAddress="169.254.0.0" subnetMask="255.255.0.0"/> <add domainName="mydomain.com"/> <remove domainName="otherdomain.com"/> </ipSecurity> </security> </system.webServer> </location>
</configuration> 

我们在ipSecurity元素里面定义策略,可以使用IP地址和域名来限制访问,但是需要显示的启用enableReverseDns=true。建议在启用域名支持时需要谨慎,因为它需要为每一个请求反向查找DNS,这是非常耗时的并且会严重限制服务器的吞吐量。使用clear元素移除任何存在的策略,然后使用add和remove定义我们的新策略。add添加新的限制,如:
<add ipAddress="192.188.100.1"/> 这样阻止处理来自该IP地址的请求,再如:<remove domainName="otherdomain.com"/> ,这样就允许来自该域名的请求。

好了,本章的笔记就到这里,还剩下最后一章的笔记,谢谢大家持续支持。希望路过的朋友留下你们的各种建议或意见:-)

原文地址:http://www.cnblogs.com/mszhangxuefei/archive/2012/06/15/mvcnotes_34.html

使用windows验证(Using Windows Authentication)【转】相关推荐

  1. WCF BasicHttpBinding 安全解析(4)windows验证(IIS宿主)

    现在我们讨论TransportCredentialOnly安全模式下的安全配置,首先在配置文件中添加如代码清单11-84所示的配置节,配置windows验证.Windows凭据认证是基于Windows ...

  2. 微软服务器认证查询,Windows验证

    Windows验证 使用Windows域控制器验证在目录服务器上有自己账户的用户时,请指定此验证方法.如果用户在目录服务器上没有自己的帐户,就无法对其进行验证.在Windows验证下,您可以为目录服务 ...

  3. SharePoint 客户端经常弹出Windows验证登录框问题

    场景描述: Site工作人员UserA创建了一个Task,并且Assign给UserB.UserB接到来自Task List的邮件通知.这时UserA发现Assign的人错了,重新修改Task Ite ...

  4. 配置Cisco ASA and Cisco *** Client 4.x with Windows 2003 IAS RADIUS Authentication

    配置Cisco ASA and Cisco *** Client 4.x with Windows 2003 IAS RADIUS Authentication <?xml:namespace ...

  5. 微软BI 之SSRS 系列 - 报表邮件订阅中 SMTP 服务器匿名访问与 Windows验证, 以及如何成功订阅报表的实例...

    这篇文章源于在上一篇博文中有园友提出订阅 SSRS 报表时的一个问题,  于是就好好总结了一下,把有关 SSRS 报表订阅的要点和容易出现问题的地方写出来,希望对大家有所帮助! 参看上一篇博文 - S ...

  6. 从未加入域的计算机上使用Windows验证方式访问SQL Server

    背景信息 随着企业信息化建设的不断深入,业务系统越来越多,统一身份验证的需求就更加迫切,Windows的域模式毫无疑问是首选.如果你的电脑已加入域中,就可以实现单点登录访问Windows相关的应用程序 ...

  7. 采用集成的Windows验证和使用Sql Server身份验证进行数据库的登录

    采用集成的Windows验证和使用Sql Server身份验证进行数据库的登录 1.集成的Windows身份验证语法范例 1 <connectionStrings> <add nam ...

  8. 关于SQLserver 的windows验证

    由于需要跨库抽取数据,并且存入到本地的数据库.两个数据库都是SQL server.其中一个数据库采用的是windows验证. tomcat部分 1,windows server服务器上,把tomcat ...

  9. mybatis学习(10): sql server身份验证和windows身份验证

    SQL Server 支持两种身份验证模式,即 Windows 身份验证模式和混合模式. Windows 身份验证是默认模式(通常称为集成安全),因为此 SQL Server 安全模型与 Window ...

最新文章

  1. Python超简单容易上手的画图工具库
  2. 又一个放弃P10千万年薪出走阿里的CTO!
  3. java自定义异常返回_Java自定义异常
  4. HMAC算法及其应用
  5. 印刷体是什么意思_家长晒出4年级小学霸课前笔记,字迹堪比“印刷体”,老师都羡慕...
  6. 揭秘“清华园”的“N”种打开方式!
  7. Nginx配置HTTP2.0
  8. 转载--Defunct僵尸进程
  9. 计算机科学与技术的主要研究方向,计算机科学与技术学科方向与特色
  10. VMware ThinApp应用程序虚拟化工具
  11. Python 训练 Day 15
  12. Win10系统彻底关闭自动更新方法——亲测有效
  13. python 控制键盘鼠标库pynput详解
  14. 通过 adb 设置音量
  15. python 网格交易源码_网格交易策略[tb源码]
  16. https://imgsa.baidu.com/forum/pic/item/...【贴吧图床】
  17. python自省与反射
  18. java.lang.RuntimeException: Performing stop of activity that is not resumed OOM了也会造成之前Activity被系统杀掉
  19. 如何在PPT中插入校徽等Logo并修改颜色(无需下载任何软件)
  20. 淘宝商品主图销量促销价查询接口

热门文章

  1. python+django房屋出租租赁管理系统-含房东三个角色
  2. 《人人都爱经济学》 读书笔记(1)
  3. 明佳妈妈新营销谈专业分工战力倍增
  4. 三维重建(二):包裹相位以及绝对相位求解
  5. Web3社交=身份系统(DID)+数据系统
  6. kicad最小布线宽度默认是多少_智能家居装修布线详解
  7. java设计模式(7):软件设计原则之迪米特法则
  8. 软件和硬件的关系-机器码怎么转成电路状态并执行的
  9. 2、Web 窗体的基本控件——文本框控件(TextBox)
  10. 2012年11月编程语言排行榜:Objective-C有望再次成为年度语言