$ cd simple
$ ../mvnw package
$ java -jar target/*.jar
Spring Boot 与 OAuth2
本指南将向您展示如何使用“社交登录”并结合 OAuth 2.0 和 Spring Boot 来构建一个实现各种功能的示例应用程序。
所有示例都是使用 Spring Boot 和 Spring Security 作为后端的单页应用程序。前端也全部使用纯 jQuery。但是,转换为不同的 JavaScript 框架或使用服务器端渲染所需的更改将是微乎其微的。
所有示例均使用 Spring Boot 中的原生 OAuth 2.0 支持实现。
有几个示例应用程序互相借鉴,并在每个步骤中添加新功能。
| 要从一个应用程序迁移到下一个应用程序所需进行的更改可以在 源代码 中跟踪。每个应用程序版本都有自己的目录,因此您可以比较它们的差异。 |
每个应用程序都可以导入到 IDE 中。您可以运行 SocialApplication 中的 main 方法来启动应用程序。它们都会在 https://:8080 上启动主页(如果您想登录并查看内容,它们都需要您至少拥有一个 GitHub 和 Google 帐户)。
您还可以使用 mvn spring-boot:run 在命令行上运行所有应用程序,或者通过构建 jar 文件并使用 mvn package 和 java -jar target/*.jar 来运行它们(根据 Spring Boot 文档 和其他 可用文档)。如果您使用顶层的 包装器,则无需安装 Maven,例如:
所有应用程序都在 localhost:8080 上运行,因为它们将使用为该地址注册的 GitHub 和 Google 的 OAuth 2.0 客户端。要在其他主机或端口上运行它们,您需要以这种方式注册您的应用程序。如果您使用默认值,不会有泄露凭据超出 localhost 的风险。但是,请谨慎处理您在 Internet 上暴露的内容,并且不要将您自己的应用程序注册信息放入公共源代码控制中。 |
使用 GitHub 进行单点登录
在本节中,您将创建一个使用 GitHub 进行身份验证的最小应用程序。通过利用 Spring Boot 的自动配置功能,这将非常容易。
创建新项目
首先,您需要创建一个 Spring Boot 应用程序,这可以通过多种方式完成。最简单的方法是访问 https://start.spring.io 并生成一个空项目(选择“Web”依赖作为起点)。同样,也可以在命令行上执行此操作:
$ mkdir ui && cd ui
$ curl https://start.spring.io/starter.tgz -d style=web -d name=simple | tar -xzvf -
然后,您可以将该项目导入您喜欢的 IDE(默认情况下它是一个普通的 Maven Java 项目),或者直接在命令行上处理文件和 mvn。
添加主页
在您的新项目中,在 src/main/resources/static 文件夹中创建 index.html。您应该添加一些样式表和 JavaScript 链接,使结果如下所示:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>Demo</title>
<meta name="description" content=""/>
<meta name="viewport" content="width=device-width"/>
<base href="/"/>
<link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css"/>
<script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
<script type="text/javascript" src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<h1>Demo</h1>
<div class="container"></div>
</body>
</html>
这一切对于演示 OAuth 2.0 登录功能都不是必需的,但最终拥有一个令人愉悦的用户界面将是很好的,所以您最好还是从主页上的一些基本内容开始。
如果您启动应用程序并加载主页,您会注意到样式表尚未加载。所以,您还需要通过添加 jQuery 和 Twitter Bootstrap 来添加它们:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
最后的依赖是 webjars "locator",它由 webjars 网站提供为一个库。Spring 可以使用 locator 在 webjars 中查找静态资源,而无需知道确切的版本(因此 index.html 中的链接是无版本的 /webjars/**)。只要您不关闭 MVC 自动配置,webjar locator 在 Spring Boot 应用程序中默认激活。
完成这些更改后,您的应用程序应该有一个外观漂亮的主页。
使用 GitHub 和 Spring Security 保护应用程序
要使应用程序安全,您可以简单地添加 Spring Security 作为依赖项。由于您想要进行“社交”登录(委托给 GitHub),因此您应该包含 Spring Security OAuth 2.0 客户端启动器:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
添加此项后,它将默认使用 OAuth 2.0 保护您的应用程序。
接下来,您需要配置您的应用程序以使用 GitHub 作为身份验证提供商。为此,请执行以下操作:
添加新的 GitHub 应用
要使用 GitHub 的 OAuth 2.0 身份验证系统进行登录,您必须首先添加一个新的 GitHub 应用。
选择“New OAuth App”,然后会出现“Register a new OAuth application”页面。输入应用程序名称和描述。然后,输入您的应用程序的主页,在本例中应为 https://:8080。最后,将授权回调 URL 指定为 https://:8080/login/oauth2/code/github,然后单击Register Application。
OAuth 重定向 URI 是用户代理在用户通过 GitHub 身份验证并授权应用程序访问后被重定向回的应用程序路径,位于Authorize application页面上。
默认的重定向 URI 模板是 {baseUrl}/login/oauth2/code/{registrationId}。registrationId 是 ClientRegistration 的唯一标识符。 |
配置 application.yml
然后,要生成到 GitHub 的链接,请将以下内容添加到您的 application.yml 文件中:
spring:
security:
oauth2:
client:
registration:
github:
clientId: github-client-id
clientSecret: github-client-secret
# ...
只需使用您刚刚创建的 GitHub OAuth 2.0 凭据,将 github-client-id 替换为客户端 ID,将 github-client-secret 替换为客户端密钥。
启动应用程序
进行此更改后,您可以再次运行应用程序并访问 https://:8080 上的主页。现在,您不会看到主页,而是会被重定向到使用 GitHub 登录。如果您这样做,并接受任何授权请求,您将被重定向回本地应用程序,主页将可见。
如果您保持登录 GitHub 状态,即使您在新浏览器中打开应用程序,没有任何 cookie 或缓存数据,您也不需要重新进行身份验证。(这就是单点登录的含义。)
| 如果您正在使用示例应用程序进行本节的学习,请确保清除浏览器缓存中的 cookie 和 HTTP Basic 凭据。对于单个服务器,最好的方法是打开一个新的隐私窗口。 |
刚刚发生了什么?
您刚编写的应用程序在 OAuth 2.0 术语中是一个客户端应用程序,它使用授权码授权流程从 GitHub(授权服务器)获取访问令牌。
然后,它使用访问令牌从 GitHub 请求一些个人详细信息(仅限于您允许它执行的操作),包括您的登录 ID 和姓名。在此阶段,GitHub 作为资源服务器,解码您发送的令牌,并检查它是否授予应用程序访问用户详细信息的权限。如果该过程成功,应用程序会将用户详细信息插入 Spring Security 上下文中,以便您被身份验证。
如果您在浏览器工具(Chrome 或 Firefox 中的 F12)中查看并跟踪所有跳转的网络流量,您将看到与 GitHub 的重定向往返,最后您将回到主页,并看到一个新的 Set-Cookie 标头。此 cookie(默认情况下为 JSESSIONID)是您在 Spring(或任何基于 Servlet 的)应用程序中的身份验证详细信息的令牌。
因此,我们有了一个安全的应用程序,这意味着要查看任何内容,用户都必须通过外部提供商(GitHub)进行身份验证。
对于网上银行网站,我们不会这样做。但对于基本身份识别目的,以及为了区分您网站上不同用户的原始内容,这是一个极好的起点。这就是为什么这种身份验证方式在当今如此受欢迎。
在下一节中,我们将为应用程序添加一些基本功能。我们还将使已登录用户在最初重定向到 GitHub 时更加明确。
添加欢迎页面
在本节中,您将修改您刚刚构建的简单应用程序,添加一个显式的 GitHub 登录链接。而不是立即重定向,新链接将显示在主页上,用户可以选择登录或保持未认证状态。只有当用户点击链接后,才会渲染受保护的内容。
主页上的条件内容
要根据用户是否已认证来渲染内容,您可以选择服务器端或客户端渲染。
在这里,您将使用 JQuery 修改客户端,尽管如果您更喜欢使用其他工具,翻译客户端代码应该不难。
为了开始动态内容,您需要像这样标记几个 HTML 元素:
<div class="container unauthenticated">
With GitHub: <a href="/oauth2/authorization/github">click here</a>
</div>
<div class="container authenticated" style="display:none">
Logged in as: <span id="user"></span>
</div>
默认情况下,第一个 <div> 将显示,第二个将不显示。注意还有一个带有 id 属性的空 <span>。
稍后,您将添加一个服务器端端点,该端点将返回已登录用户的详细信息作为 JSON。
但是,首先,添加以下 JavaScript,它将调用该端点。根据端点的响应,此 JavaScript 将使用用户的姓名填充 <span> 标签,并相应地切换 <div>:
<script type="text/javascript">
$.get("/user", function(data) {
$("#user").html(data.name);
$(".unauthenticated").hide()
$(".authenticated").show()
});
</script>
请注意,此 JavaScript 期望服务器端端点被调用为 /user。
/user 端点
现在,您将添加前面提到的服务器端端点,并将其命名为 /user。它将返回当前登录的用户,我们可以在主类中轻松完成:
@SpringBootApplication
@RestController
public class SocialApplication {
@GetMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
return Collections.singletonMap("name", principal.getAttribute("name"));
}
public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}
}
注意 @RestController、Geth ttpMapping 和注入到处理程序方法中的 OAuth2User 的用法。
将整个 OAuth2User 返回到端点不是一个好主意,因为它可能包含您不希望向浏览器客户端透露的信息。 |
使主页公开
您还需要做最后一次更改。
此应用程序现在可以正常工作并按原样进行身份验证,但仍然会在显示页面之前重定向。为了使链接可见,我们还需要通过扩展 WebSecurityConfigurerAdapter 来关闭主页上的安全。
@SpringBootApplication
@RestController
public class SocialApplication extends WebSecurityConfigurerAdapter {
// ...
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests(a -> a
.antMatchers("/", "/error", "/webjars/**").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(e -> e
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
)
.oauth2Login();
// @formatter:on
}
}
Spring Boot 对带有 @SpringBootApplication 注释的类上的 WebSecurityConfigurerAdapter 附加了特殊含义:它使用它来配置包含 OAuth 2.0 身份验证处理程序的安全过滤器链。
上述配置指示了一个允许的端点白名单,所有其他端点都需要进行身份验证。
您希望允许:
-
/因为这是您刚刚动态生成的页面,其中一些内容对未认证用户可见。 -
/error因为这是 Spring Boot 用于显示错误的端点,以及 -
/webjars/**因为您希望您的 JavaScript 对所有访问者运行,无论他们是否已认证。
您在此配置中看不到关于 /user 的任何内容。因为末尾的 .anyRequest().authenticated() 配置,所有内容(包括 /user)都保持安全,除非另有说明。
最后,由于我们通过 Ajax 与后端进行交互,因此我们希望配置端点以响应 401 而不是默认的重定向到登录页面的行为。配置 authenticationEntryPoint 可以为我们实现这一点。
完成这些更改后,应用程序就完成了。如果您运行它并访问主页,您应该会看到一个样式精美的 HTML 链接“使用 GitHub 登录”。该链接不会直接带您到 GitHub,而是带您到处理身份验证的本地路径(并发送重定向到 GitHub)。一旦您通过身份验证,您将被重定向回本地应用程序,在那里它会显示您的名字(假设您已在 GitHub 中设置了允许访问该数据的权限)。
添加注销按钮
在本节中,我们将修改我们已经构建的点击应用程序,添加一个按钮,允许用户注销该应用程序。这似乎是一个简单的功能,但实现起来需要一些技巧,因此值得花一些时间来精确地讨论如何实现它。大部分更改都与我们将应用程序从只读资源转换为读写资源(注销需要状态更改)有关,因此任何不是纯静态内容的实际应用程序都需要进行相同的更改。
客户端更改
在客户端,我们只需要提供一个注销按钮和一些 JavaScript 来调用服务器以取消身份验证。首先,在 UI 的“已认证”部分,我们添加按钮:
<div class="container authenticated">
Logged in as: <span id="user"></span>
<div>
<button onClick="logout()" class="btn btn-primary">Logout</button>
</div>
</div>
然后,我们在 JavaScript 中提供它引用的 logout() 函数:
var logout = function() {
$.post("/logout", function() {
$("#user").html('');
$(".unauthenticated").show();
$(".authenticated").hide();
})
return true;
}
logout() 函数向 /logout 发送 POST 请求,然后清除动态内容。现在我们可以切换到服务器端来实现该端点。
添加注销端点
Spring Security 内置了对 /logout 端点的支持,它将为我们做正确的事情(清除会话并使 cookie 无效)。要配置端点,我们只需扩展 WebSecurityConfigurerAdapter 中的现有 configure() 方法:
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
// ... existing code here
.logout(l -> l
.logoutSuccessUrl("/").permitAll()
)
// ... existing code here
// @formatter:on
}
/logout 端点需要我们对其进行 POST 请求,并且为了保护用户免受跨站点请求伪造(CSRF,发音为“sea surf”)的侵害,它需要一个令牌包含在请求中。令牌的值与当前会话相关联,这就是提供保护的原因,因此我们需要一种方法将此数据放入我们的 JavaScript 应用程序中。
许多 JavaScript 框架内置了对 CSRF 的支持(例如,在 Angular 中,它们称之为 XSRF),但它们的实现方式通常与 Spring Security 的开箱即用行为略有不同。例如,在 Angular 中,前端会希望服务器发送一个名为“XSRF-TOKEN”的 cookie,如果看到它,它会将其值作为名为“X-XSRF-TOKEN”的标头发送回来。我们可以使用简单的 jQuery 客户端实现相同的行为,然后服务器端更改将与具有零个或极少更改的其他前端实现一起工作。为了让 Spring Security 了解这一点,我们需要添加一个创建 cookie 的过滤器。
在 WebSecurityConfigurerAdapter 中,我们执行以下操作:
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
// ... existing code here
.csrf(c -> c
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
)
// ... existing code here
// @formatter:on
}
在客户端添加 CSRF 令牌
由于在此示例中我们没有使用更高级别的框架,因此您需要显式添加 CSRF 令牌,您刚刚将其作为 cookie 从后端可用。为了使代码更简单一些,请包含 js-cookie 库:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>js-cookie</artifactId>
<version>2.1.0</version>
</dependency>
然后,您可以在 HTML 中引用它:
<script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script>
最后,您可以在 XHR 中使用 Cookies 的便利方法:
$.ajaxSetup({
beforeSend : function(xhr, settings) {
if (settings.type == 'POST' || settings.type == 'PUT'
|| settings.type == 'DELETE') {
if (!(/^http:.*/.test(settings.url) || /^https:.*/
.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-XSRF-TOKEN",
Cookies.get('XSRF-TOKEN'));
}
}
}
});
准备就绪!
完成这些更改后,我们就可以运行应用程序并尝试新的注销按钮了。在一个新的浏览器窗口中启动应用程序并加载主页。单击“登录”链接跳转到 GitHub(如果您已登录,您可能不会注意到重定向)。单击“注销”按钮以取消当前会话并使应用程序恢复到未认证状态。如果您感到好奇,应该可以看到浏览器与本地服务器交换的请求中的新 cookie 和标头。
请记住,现在注销端点正在与浏览器客户端一起工作,那么所有其他 HTTP 请求(POST、PUT、DELETE 等)也将同样有效。因此,这应该是一个具有更多实际功能的应用程序的良好平台。
使用 GitHub 登录
在本节中,您将修改您已经构建的注销应用程序,添加一个贴纸页面,以便最终用户可以在多组凭据之间进行选择。
让我们为最终用户添加 Google 作为第二个选项。
初始设置
要使用 Google 的 OAuth 2.0 身份验证系统进行登录,您必须在 Google API Console 中设置一个项目以获取 OAuth 2.0 凭据。
| Google 的 OAuth 2.0 实现用于身份验证,符合OpenID Connect 1.0 规范,并且已获得 OpenID 认证。 |
请按照OpenID Connect页面上的说明进行操作,从“Setting up OAuth 2.0”部分开始。
完成“Obtain OAuth 2.0 credentials”说明后,您应该会获得一个新的 OAuth Client,其凭据包含客户端 ID 和客户端密钥。
设置重定向 URI
此外,您还需要提供一个重定向 URI,就像之前为 GitHub 所做的那样。
在“Set a redirect URI”子部分中,确保将Authorized redirect URIs字段设置为 https://:8080/login/oauth2/code/google。
添加客户端注册
然后,您需要配置客户端以指向 Google。由于 Spring Security 内置了对多个客户端的支持,因此您可以将 Google 凭据与为 GitHub 创建的凭据一起添加:
spring:
security:
oauth2:
client:
registration:
github:
clientId: github-client-id
clientSecret: github-client-secret
google:
client-id: google-client-id
client-secret: google-client-secret
如您所见,Google 是 Spring Security 开箱即用的另一个支持的提供商。
添加登录链接
在客户端,更改很简单——您只需添加另一个链接:
<div class="container unauthenticated">
<div>
With GitHub: <a href="/oauth2/authorization/github">click here</a>
</div>
<div>
With Google: <a href="/oauth2/authorization/google">click here</a>
</div>
</div>
URL 中的最终路径应与 application.yml 中的客户端注册 ID 匹配。 |
Spring Security 提供了一个默认的提供商选择页面,可以通过指向 /login 而不是 /oauth2/authorization/{registrationId} 来访问。 |
如何添加本地用户数据库
许多应用程序需要保留其用户数据,即使身份验证委托给了外部提供商。我们在此处未显示代码,但可以轻松地分两步完成。
-
选择一个数据库后端,并设置一些存储库(例如,使用 Spring Data)来存储满足您需求且可以从外部身份验证完全或部分填充的自定义
User对象。 -
实现并公开
OAuth2UserService以便调用授权服务器以及您的数据库。您的实现可以委托给默认实现,后者将执行调用授权服务器的繁重工作。您的实现应该返回一个扩展了自定义User对象并实现了OAuth2User的对象。
提示:在 User 对象中添加一个字段,用于链接到外部提供商中的唯一标识符(不是用户的名字,而是外部提供商帐户的唯一标识符)。
为未认证用户添加错误页面
在本节中,您将修改您之前构建的双提供商应用程序,为无法进行身份验证的用户提供一些反馈。同时,您将扩展身份验证逻辑,包括一个规则,该规则仅允许属于特定 GitHub 组织的成员。 “组织”是 GitHub 特定于域的概念,但可以为其他提供商制定类似的规则。例如,使用 Google,您可能只想允许来自特定域的用户进行身份验证。
切换到 GitHub
双提供商示例使用 GitHub 作为 OAuth 2.0 提供商。
spring:
security:
oauth2:
client:
registration:
github:
client-id: bd1c0a783ccdd1c9b9e4
client-secret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
# ...
在客户端检测身份验证失败
在客户端,您可能希望为无法进行身份验证的用户提供一些反馈。为了方便起见,您可以添加一个 div,您最终将在其中添加一条信息性消息。
<div class="container text-danger error"></div>
然后,添加对 /error 端点的调用,用结果填充 <div>:
$.get("/error", function(data) {
if (data) {
$(".error").html(data);
} else {
$(".error").html('');
}
});
error() 函数会从后端检查是否有任何错误需要显示。
添加错误消息
为了支持检索错误消息,您需要在身份验证失败时捕获它。为此,您可以配置一个 AuthenticationFailureHandler,如下所示:
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
// ... existing configuration
.oauth2Login(o -> o
.failureHandler((request, response, exception) -> {
request.getSession().setAttribute("error.message", exception.getMessage());
handler.onAuthenticationFailure(request, response, exception);
})
);
}
上述代码将在每次身份验证失败时将错误消息保存到会话中。
然后,您可以添加一个简单的 /error 控制器,如下所示:
@GetMapping("/error")
public String error(HttpServletRequest request) {
String message = (String) request.getSession().getAttribute("error.message");
request.getSession().removeAttribute("error.message");
return message;
}
这将替换应用程序中默认的 /error 页面,这在我们的情况下是可以的,但可能不够复杂,无法满足您的需求。 |
在服务器端生成 401
如果用户无法或不想使用 GitHub 登录,Spring Security 已经会生成 401 响应,因此如果身份验证失败(例如,通过拒绝令牌授权),应用程序已经可以正常工作。
为了增加一些趣味性,您可以扩展身份验证规则以拒绝不在正确组织的用户的访问。
您可以使用 GitHub API 来了解有关用户的更多信息,因此您只需要将其插入身份验证过程的正确部分。
幸运的是,对于如此简单的用例,Spring Boot 提供了一个简单的扩展点:如果您声明了一个类型为 OAuth2UserService 的 @Bean,它将被用于识别用户主体。您可以使用该钩子来断言用户是否属于正确的组织,如果不是则抛出异常:
@Bean
public OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService(WebClient rest) {
DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();
return request -> {
OAuth2User user = delegate.loadUser(request);
if (!"github".equals(request.getClientRegistration().getRegistrationId())) {
return user;
}
OAuth2AuthorizedClient client = new OAuth2AuthorizedClient
(request.getClientRegistration(), user.getName(), request.getAccessToken());
String url = user.getAttribute("organizations_url");
List<Map<String, Object>> orgs = rest
.get().uri(url)
.attributes(oauth2AuthorizedClient(client))
.retrieve()
.bodyToMono(List.class)
.block();
if (orgs.stream().anyMatch(org -> "spring-projects".equals(org.get("login")))) {
return user;
}
throw new OAuth2AuthenticationException(new OAuth2Error("invalid_token", "Not in Spring Team", ""));
};
}
请注意,此代码依赖于 WebClient 实例,以便代表已认证用户访问 GitHub API。完成此操作后,它会循环遍历组织,查找与“spring-projects”匹配的一个(这是用于存储 Spring 开源项目的组织)。如果您想成功进行身份验证且您不在 Spring 工程团队中,您可以替换为您自己的值。如果没有匹配项,它将抛出 OAuth2AuthenticationException,Spring Security 会捕获此异常并将其转换为 401 响应。
WebClient 也必须创建为一个 bean,但这很简单,因为通过使用 spring-boot-starter-oauth2-client,它的组件都是可自动装配的。
@Bean
public WebClient rest(ClientRegistrationRepository clients, OAuth2AuthorizedClientRepository authz) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(clients, authz);
return WebClient.builder()
.filter(oauth2).build();
}
显然,上面的代码可以推广到其他身份验证规则,有些适用于 GitHub,有些适用于其他 OAuth 2.0 提供商。您只需要 WebClient 和一些关于提供商 API 的知识。 |
结论
我们已经看到如何使用 Spring Boot 和 Spring Security 以各种风格轻松构建应用程序。所有示例中的主要主题是使用外部 OAuth 2.0 提供商进行身份验证。
所有示例应用程序都可以轻松扩展和重新配置以适应更具体的用例,通常只需更改配置文件即可。请记住,如果您在自己的服务器中使用示例版本,请在 GitHub(或类似服务)上注册并获取您自己的主机地址的客户端凭据。并记住不要将这些凭据放入源代码控制中!
想写新指南或为现有指南做贡献吗?请查看我们的贡献指南。
| 所有指南的代码均采用 ASLv2 许可,文字内容采用署名-禁止演绎知识共享许可。 |