“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。

在本文中,您将研究使用Spring Boot 2.1实现登录功能的各种选项。 您将从最简单的基本身份验证开始,除了内部后端工具外,您可能永远不想使用它,然后转到简单的基于表单的身份验证页面。 接下来,您将通过覆盖一些默认模板和控制器来自定义默认的,自动生成的表单。 最后,您将继续使用OAuth 2.0添加单一登录。 您将看到如何允许用户使用Github和Okta登录。

本教程的假设是非常基本的。 我假设您已经对Spring和Spring Boot有了基本的了解,但是不一定对Spring Security或Spring的各种安全功能有深入的了解。 您将需要安装git ,并且gradle会很好,但是您可以对所有gradle命令使用Gradle包装器,因此这并不是绝对必要的。

继续克隆我为本教程创建的存储库 :

git clone https://github.com/oktadeveloper/okta-spring-boot-login-options-example.git

该存储库包含五个子目录:

  • basic-auth
  • form-auth
  • custom-form-auth
  • oauth-start
  • oauth-okta-github
  • oauth-okta-starter

这些对应于本教程的四个部分(最后三个部分是OAuth部分,其中三个部分)。 除了oauth-start ,这些都是功能齐全的应用程序。 在本教程中,您将遍历代码的含义以及如何构建它们。

在Spring Boot中构建HTTP基本登录

基本身份验证是基本的。 这是直接内置在HTTP协议中的简单方案。 它来自田园时代,大量的数据和金钱流过互联网的各种管道。 因此,它确实不是非常安全。 根据规范,密码和用户名使用HTTP authorization标头中的Base64进行编码。 因为Base64可能也是纯文本格式,所以如果您要对任何内容使用基本身份验证,请确保始终使用HTTPS / SSL,因为每个请求都将发送身份验证凭据。

使用您喜欢的IDE或编辑器打开basic-auth Spring Boot项目。

您要签出的第一件事是build.gradle文件。 复制如下。 我不会详细介绍所有这些内容,但是如果您还不熟悉,我想让您了解这里发生的一些事情。

plugins {  id 'org.springframework.boot' version '2.1.4.RELEASE'  id 'java'
}  apply plugin: 'io.spring.dependency-management'  group = 'com.okta.springsecurityauth'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'  repositories {  mavenCentral()
}  dependencies {  implementation 'org.springframework.boot:spring-boot-starter-security'  implementation 'org.springframework.boot:spring-boot-starter-web'  testImplementation 'org.springframework.boot:spring-boot-starter-test'  testImplementation 'org.springframework.security:spring-security-test'
}

有两个Spring插件被添加到构建中: org.springframework.bootio.spring.dependency-management 。 请注意,版本设置为2.1.4.RELEASE 。 过去,Spring的真正麻烦之一就是依赖管理。 Spring是一个庞大的库集合,当您引入一个库时,您需要引入其他具有兼容版本的库。 当您更新一个时,通常这会导致其他人失去兼容性。 过去解决此问题可能会使您陷入所谓的“依赖地狱”。

幸运的是,Spring使事情变得更加轻松。 查看我们的两个Spring依赖项:

dependencies {  implementation 'org.springframework.boot:spring-boot-starter-security'  implementation 'org.springframework.boot:spring-boot-starter-web'
...
}

请注意,它们没有版本号。 这些基本上是功能集(在这种情况下为安全性和Web)的大型元依赖项,并且Spring插件根据此行中设置的版本为您管理所有子依赖项:

id 'org.springframework.boot' version '2.1.4.RELEASE'

build.gradle文件的全部执行摘要将加载Spring Boot版本2.1.4,并将添加Web和安全功能模块。 Spring的所有可用启动程序的列表可以在其docs中找到 。

除了gradle.file ,实际上只有三个其他感兴趣的文件,所有Java文件。 在src/main/java/com/okta/springsecurityauth查看,您将看到它们:

  • Application.java (自动魔术化整个Spring Boot框架的主类)
  • SecurityConfiguration.java (配置安全性选项)
  • WebController.java (非常基本的HTTP请求控制器)

Application.javaApplication.java的入口点。 在这种情况下,而且在许多情况下,这非常简单。 最重要的是@SpringBootApplication批注,它告诉您的Spring依赖项引导整个Spring Boot框架。 当然,还有main()方法,这是Spring加载和运行Application类的地方。

package com.okta.springsecurityauth;  import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;  @SpringBootApplication
public class Application {  public static void main(String[] args) {  SpringApplication.run(Application.class, args);  }  }

WebController.java足够聪明,它是您的Web请求控制器。 它定义了请求端点并确定了响应。

package com.okta.springsecurityauth;  import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;  @Controller
public class WebController {  @RequestMapping("/")  @ResponseBody  public String index() {  return "That's pretty basic!";  }  }

在这种情况下,Web控制器将返回一个简单的字符串,而不是路由到模板文件,这将在稍后介绍。 @ResponseBody批注允许该方法直接返回字符串。

在本教程中, SecurityConfiguration.java是执行操作的地方。 这是Spring Boot配置为使用基本身份验证的地方。 您还可以在这里配置硬编码的默认用户名和密码(显然,这不是我在生产中要做的,但是非常适合教程)。

package com.okta.springsecurityauth;  import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  @Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {  @Override  public void configure(HttpSecurity http) throws Exception {  http  .authorizeRequests()  .anyRequest().authenticated()  .and()  .httpBasic();  }  @Override  protected void configure(AuthenticationManagerBuilder auth) throws Exception {  auth.inMemoryAuthentication()  .withUser("user")  .password("{noop}pass") // Spring Security 5 requires specifying the password storage format  .roles("USER");  }  }

如果您查看configure()方法,您将看到http对象及其流畅接口用于告诉spring认证所有请求并使用HTTP基本认证。 这是相当琐碎的,但是稍后您将在此界面中看到大量功能。

configure()方法主要是本教程的一个技巧,目的是在内存身份验证管理器中创建用户。 您正在使用用户名user和password pass创建一个用户。 用户已分配了USER角色。

而已!

打开终端,并确保您位于basic-auth项目的根目录中。 使用以下命令运行项目:

./gradlew bootRun

等待Spring Boot应用完成加载。

导航到http://localhost:8080

您会看到一个登录窗口。


使用user登录并作为凭据pass

系统将显示一个成功屏幕,显示“这很简单!”

配置基于Spring Boot Form的登录

使用基本身份验证时,登录表单实际上是由浏览器而不是由应用程序生成的。 它显示为无样式的弹出窗口。 这不是很好的流程,也不是非常专业的外观。

只需对代码进行一些很小的更改,您就可以让Spring Boot自动生成外观更专业的登录表单。 可以在GitHub存储库的form-auth子目录中找到完整的代码,或者如果仍然打开,则可以仅对basic-auth项目进行更改。

您想要将SecurityConfiguration.java文件的configure()方法更改为如下所示:

@Override
public void configure(HttpSecurity http) throws Exception {  http  .authorizeRequests()  .anyRequest().authenticated()  .and()  .formLogin()  .and()  .httpBasic();
}

唯一的不同是添加了.and().formLogin() 。 除此之外,这两个项目是相同的。

使用./gradlew bootRun再次运行它。

导航到http://localhost:8080 (您可能需要打开一个隐身窗口以触发重新认证)。

这次,您将看到Spring为您生成的登录页面。


自定义Spring Boot登录表单

我们日益复杂的Spring Boot身份验证过程的下一步是自定义登录表单。 Spring使这个超级容易。 但是,有许多新文件,并且对代码的更改比上次更多,因此我建议打开在回购的custom-form-auth文件夹下找到的项目。

build.gradle文件中,有一个新的依赖项。 这引入了Thymeleaf模板引擎,这是与Spring Boot一起使用的默认Web模板引擎。

dependencies {  ...implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'  ...
}

现在, SecurityConfiguration.java文件如下所示(为简洁起见,省略了一些部分):

package com.okta.springsecurityauth;  ...@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {  @Override  public void configure(HttpSecurity http) throws Exception {  http  .authorizeRequests()  .antMatchers( "/public/**").permitAll()  .anyRequest().authenticated()  .and()  .formLogin()  .loginPage("/login.html")  .failureUrl("/login-error.html")  .permitAll();  }...}

请注意, .httpBasic()已消失, .formLogin()具有一些新选项。 在这里,您将设置一个登录页面和一个登录失败页面,并确保它们是公开可用的。

还要注意这一行:

.antMatchers( "/public/**").permitAll()

在这里,您无需进行身份验证即可使类路径根目录上的public目录可用。 在src/main/resources/static有一个public目录。 启动该应用程序时, src/main/resources/static目录下的所有内容都将复制到类路径,因此public目录最终位于类路径根目录下,并且其中的所有文件无需身份验证即可使用。 这非常适合图像,JavaScript文件和CSS文件之类的东西。

WebController.java也有一些新的端点:

package com.okta.springsecurityauth;  ...@Controller
public class WebController {  @RequestMapping("/")  @ResponseBody  public String index() {  return "You made it!";  }  // Login form  @RequestMapping("/login.html")  public String login() {  return "login.html";  }  // Login form with error  @RequestMapping("/login-error.html")  public String loginError(Model model) {  model.addAttribute("loginError", true);  return "login.html";  }  }

注意,虽然index()方法具有@RequestBody批注,这意味着它将直接以字符串形式返回其请求主体,但login()loginError()方法却没有。 相反,他们返回的是Spring Boot将呈现的Thymeleaf模板的名称。 默认情况下,这些模板位于src/main/resources/templates 。 另外,请注意, loginError()有点路由技巧。 实际上,它只是返回login.html模板,但在模型中注入了error属性。

src/main/resources/templates/login.html是一个新文件。 这是登录模板文件。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>  <title>Login page</title>  <link th:href="@{/public/style.css}" rel="stylesheet" />
</head>
<body>
<div id="container">  <h2>Login page</h2>  <form th:action="@{/login.html}" method="post">  <label for="username">Username</label>  <input type="text" id="username" name="username" autofocus="autofocus" />  <label for="password">Password</label>  <input type="password" id="password" name="password" />  <input id="submit" type="submit" value="Log in" />  </form>  <p th:if="${loginError}" class="error">Wrong user or password</p>
</div>
</body>
</html>

关于Thymeleaf的真实,深入的解释远远超出了本教程的范围。 如果愿意,请访问他们的网站进行深入研究。

还记得您将public目录公开吗? 这行有一个非常基本的样式表。 通常,我将其包括在内是为了演示一种在模板文件中包含静态资源的方法。

<link th:href="@{/public/style.css}" rel="stylesheet" />

根据模型的loginError属性有条件地呈现错误行,该属性由控制器的loginError()方法注入。

<p th:if="${loginError}" class="error">Wrong user or password</p>

除此之外,这是一个非常简单的登录表单!

再次使用./gradlew bootRun运行它。

您将看到样式化的定制登录表单:


使用user:pass再次登录,您将看到我们的成功屏幕,显示“您成功了!”

使用GitHub和Single Sign-On的Spring Boot OAuth 2.0登录

到目前为止,您已经使用临时内存AuthenticationManager在本地完成了所有AuthenticationManager 。 在生产中更常见的是,应用程序支持OAuth 2.0和OIDC(开放ID连接)。 OAuth 2.0是开放的授权标准。 OIDC建立在OAuth 2.0之上,并添加了身份验证,以实现更完整的身份管理协议。

在本教程中,您首先将看到如何使用GitHub添加单点登录(SSO)。 之后,您将看到如何使用软件即服务身份解决方案提供商Okta。

两者都非常简单,并且允许用户重用现有的身份提供者确实有好处。 强迫用户处理和管理数百个网站的单独的强密码是一个愚蠢的事情,最终会导致弱密码和在多个站点之间重复使用的密码(乘以其易受攻击性); 更不用说旧的“只是在便签上随意写,然后将其粘贴到显示器上”密码管理解决方案。

通过GitHub Single Sign-on简化您的Spring Boot App登录

现在是时候实现GitHub OAuth 2.0客户端了。

首先,您需要在GitHub上注册一个新的OAuth应用程序。 转到他们的网站并立即执行此操作。 填写如下所示的值。

请特别注意Authorization回调URL ,因为它需要为http://localhost:8080/login/oauth2/code/github


单击注册应用程序 。 请注意客户端ID客户端密钥,因为您很快就会需要它们。

现在,回到Java。 在您的IDE中打开oauth-start项目。

build.gradle文件中,注意几个新的依赖项:

...
dependencies {  implementation 'org.springframework.boot:spring-boot-starter-security'  implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'  implementation 'org.springframework.boot:spring-boot-starter-web'  implementation 'org.springframework.security:spring-security-oauth2-client'  implementation 'org.springframework.security:spring-security-oauth2-jose'  ...
}

安全性,Thymeleaf和网络启动程序仍然存在。 但是,有两个新的Spring启动器: oauth2-clientoauth2-jose

oauth2-client了实现OAuth 2.0客户端所需的库。 oauth2-jose了一些用于签名和加密的通用库。 JOSE代表Java对象签名和加密。

OConfiguration登录的SecurityConfiguration.java文件已更新:

package com.okta.spring.SpringBootOAuth;
...@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {  @Override  public void configure(HttpSecurity http) throws Exception {  http.antMatcher("/**")  .authorizeRequests()  .antMatchers("/", "/login**").permitAll()  .anyRequest().authenticated()  .and()  .oauth2Login();  }
}

需要注意的两件事:1)对/login所有请求都是公共的,以及2) oauth2Login()方法是导致Spring Boot配置OAuth 2.0客户端的原因。

如果这似乎太简单了 ,那是正确的。 一些配置已移至application.yml文件。

打开src/main/resources/application.yml文件:

spring:  thymeleaf:  cache: false  security:  oauth2:  client:  registration:  github:  client-id: << your GitHub client ID>>  client-secret: << your GitHub client secret >>

您需要从上方将Client IDClient Secret填写到该文件中。

Web路由和模板也已更改。 查看WebController.java文件:

package com.okta.spring.SpringBootOAuth;  ...@Controller
public class WebController {  @RequestMapping("/securedPage")  public String securedPage(Model model,  @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,  @AuthenticationPrincipal OAuth2User oauth2User) {  model.addAttribute("userName", oauth2User.getName());  model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName());  model.addAttribute("userAttributes", oauth2User.getAttributes());  return "securedPage";  }  @RequestMapping("/")  public String index() {  return "index";  }  }

该控制器定义了两个端点,这些端点返回两个模板文件:

  • / –> src/main/resources/templates/index.html
  • /securedPage –> src/main/resources/templates/securedPage.html

securedPage()方法中,请注意如何使用依赖性注入来获取有关已认证用户的信息,以便可以将其注入模型中,然后将其传递给模板文件。

src/main/resources/templates/index.html非常简单:

<!DOCTYPE html>
<html lang="en">
<head>  <meta charset="UTF-8">  <title>Home</title>
</head>
<body>  <h1>Spring Security SSO</h1>  <a href="securedPage">Login</a>
</body>
</html>

以及src/main/resources/templates/securedPage.html模板文件:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>  <meta charset="UTF-8">  <title>Secured Page</title>
</head>
<body>  <h1>Secured Page</h1>  <div>User Name: <span th:text="${userName}"></span></div>  <div>Client Name: <span th:text="${clientName}"></span></div>  <div>User Attributes: <span th:text="${userAttributes}"></span></div>
</body>
</html>

现在您可以尝试了。 再次,确保您在项目根目录中,然后运行./gradlew bootRun

导航到http://localhost:8080 ,然后单击“ 登录”链接。

如果您的浏览器绕过登录页面并直接进入/securedPage端点,请打开一个隐身浏览器,然后重试。

首先,您需要授权Spring Boot Login应用程序使用您的Github帐户进行OAuth登录。


接下来,您将看到GitHub OAuth登录屏幕:


如果成功,您将看到一个简单的文本页面,该页面以粗体显示“安全页面”,并显示有关您的OAuth用户的信息。

很漂亮吧?

现在,您将添加第二个OAuth提供程序:Okta。

将使用Okta登录的OAuth 2.0登录到您的Spring Boot应用

首先,如果您还没有开发人员帐户,请访问developer.okta.com并注册一个免费的开发人员帐户。

拥有帐户后,要创建OAuth / OIDC应用,请打开Okta开发人员信息中心。 单击“ 应用程序”顶部菜单项,然后单击“ 添加应用程序”

选择Web作为平台,然后单击Next

为应用命名。 我将其命名为“ Spring Boot Login”,但是您可以随意命名。

登录重定向URI更改为http://localhost:8080/login/oauth2/code/okta

其他默认值也可以。


单击完成

在下一页上记下客户端ID客户端密钥

更新Okta的application.yml文件:

spring:  ...security:  oauth2:  client:  registration:  github:  client-id: << Your GitHub Client ID >>  client-secret: << Your GitHub Client Secret >>  okta:  client-id: << Your Okta Client ID >>  client-secret: << Your Okta Client Secret >> client-name: Oktaprovider:  okta:  issuer-uri: https://{yourOktaDomain}/oauth2/default

您需要添加Okta注册和提供商条目,并确保填写您的Client IDClient Secret和Okta发行者。

重新启动应用程序,转到http://localhost:8080 ,然后单击“ 登录”链接。

这次,您将可以选择OAuth提供商。 该屏幕由Spring Boot自动生成。


单击Okta ,您将被带到Okta登录页面(通常有关注销和/或隐姓埋名的警告)。


成功登录,您将看到我们的成功页面。


至此,您已经将oauth-start项目与oauth-github-okta项目文件夹进行了更新,并且已经看到了将多个OAuth提供程序添加到Spring Boot应用程序是多么容易。

使用Okta的Spring Boot Starter简化OAuth 2.0登录

在本教程中,您要做的最后一件事是将Okta配置为允许新用户注册。 但是,在此之前,我想向您介绍Okta Spring Boot Starter。 该项目简化了Spring Boot和Okta的集成。 该项目的自述文件是获取更深入信息的好资源。

您将把Okta Spring Boot Starter集成到该项目中,并稍微简化配置。 为了简单起见,您还将删除GitHub OAuth集成。

build.gradle文件添加一个依赖build.gradle

dependencies {...implementation 'com.okta.spring:okta-spring-boot-starter:1.1.0'...
}

现在更新application.yml文件:

okta:  oauth2:  issuer: https://{yourOktaDomain}/oauth2/default  client-id: <<yourOktaClientID>>client-secret: <<yourOktaClientSecret>>
spring:  thymeleaf:  cache: false

填写您的客户密码客户ID

尝试一下。 运行./gradlew bootRun

您应该能够通过Okta登录。 这次您将无法选择OAuth 2.0提供程序。

启用用户注册

登录到您的developer.okta.com帐户。

将鼠标悬停在“ 用户”上 ,然后单击“ 注册”


启用注册。 此外,启用登录页面中的“显示“注册””链接……选项。 这将导致注册链接显示在托管登录页面中。


使用隐身窗口再次登录。 这次您会注意到该用户可以选择注册为新用户。


输入您的电子邮件地址,密码和名称; 设置一些安全性问题,您就完成了! 您使用Okta为您的应用程序注册了一个新用户。

Okta的自助注册选项可以做更多的事情。 所有这些都可以配置和定制。 看看他们的文档以进行更深入的研究。

oauth-okta-starter目录中可以找到使用Okta Spring Boot Starter并删除GitHub OAuth的最终产品。

了解有关Spring Boot登录选项和安全身份验证的更多信息

在本教程中,您涵盖了很多领域。 您使用基本身份验证,基于表单的身份验证和定制的基于表单的身份验证实现了Spring Boot应用程序。 然后,您使用OAuth 2.0和OIDC使用GitHub和Okta实施SSO。 最后,您了解了如何使用Okta Spring Boot Starter简化Spring Boot中的OAuth / OIDC SSO配置,以及如何允许用户通过Okta自助注册。

您可以在GitHub上的本教程中找到示例的所有代码。

要深入研究创建自定义登录表单,请查看有关该主题的Spring文档 。

Spring Security的oauth2login示例还提供了一些很好的信息和更多示例。

以下是一些相关的博客文章,它们演示了如何使用Spring Boot和Spring Security进行登录和身份验证:

  • Java应用程序的简单令牌认证
  • 在15分钟内使用Spring Boot和Spring Security构建一个Web应用程序
  • 创建一个安全的Spring REST API
  • 使用Spring Boot和Vue.js构建一个简单的CRUD应用

如果您喜欢这篇文章,请在社交媒体{ Twitter , Facebook , LinkedIn , YouTube }上关注我们,以了解我们何时发布类似的文章。

“ Spring Boot登录选项快速指南”最初于2019年5月15日发布在Okta开发人员博客上。

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。

翻译自: https://www.javacodegeeks.com/2019/06/quick-guide-spring-boot-options.html

Spring Boot登录选项快速指南相关推荐

  1. spring_Spring Boot登录选项快速指南

    spring "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验 ...

  2. spring boot / cloud (十七) 快速搭建注册中心和配置中心

    spring boot / cloud (十七) 快速搭建注册中心和配置中心 本文将使用spring cloud的eureka和config server来搭建. 然后搭建的模式,有很多种,本文主要聊 ...

  3. boot spring test 文档_Spring、Spring Boot 和 TestNG 测试指南 ( 3 )

    原标题:Spring.Spring Boot 和 TestNG 测试指南 ( 3 ) 来源:chanjarster, github.com/chanjarster/spring-test-exampl ...

  4. Spring Boot 2.0 迁移指南

    点击上方"朱小厮的博客",选择"设为星标" 回复"666"获取新整理的1000+GB资料 前提 本文档将帮助您把应用程序迁移到 Spring ...

  5. 使用Spring Boot和MongoDB快速进行Web应用原型设计

    回到我以前的项目之一,我被要求制作一些应急申请. 时间表紧张,范围简单. 内部编码标准是PHP,因此尝试建立经典的Java EE堆栈将是一个真正的挑战. 而且,说实话,完全过大了. 那怎么办 我趁机尝 ...

  6. Spring Boot 项目瘦身指南,瘦到不可思议!129M->1.3M

    之前在 从使用传统Web框架到切换到Spring Boot后的总结 中提到关于 Spring Boot 编译打包,Spring Boot 应用程序不用额外部署到外部容器中,可以直接通过 Maven 命 ...

  7. RabbitMQ(四):RabbitMQ与Spring Boot简单整合 快速尝鲜版

    RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.Spring Boot的兴起,极大地简化了Spring的开发,本文将使用Spring Boot与RabbitM ...

  8. 最佳实践|Spring Boot 应用如何快速接入 Prometheus 监控

    简介:SpringBoot 微服务的开发.发布与部署只占其生命周期的一小部分,应用和系统运维才是重中之重.而运维过程中,监控工作更是占据重要位置.那么,为了对系统的状态进行持续地观测,面向Spring ...

  9. Spring Boot 学习(一) 快速搭建SpringBoot 项目

    快速搭建一个 Spring Boot 项目 部分参考于<深入实践Spring Boot>.<Spring实战 第四版>与程序猿DD的有关博客. 参考(嘟嘟独立博客):http: ...

最新文章

  1. SpringBoot2.0配置redis相关
  2. 通过google app engine 在google cloud 部署支持quic的Java web 应用(多种方式)
  3. 国科大高级人工智能6-GAN
  4. C#设计模式之0-简单工厂模式
  5. 自疫情暴发以来,99%的中国IT决策者认为数据变得更重要
  6. idea svn 的使用----转载,挺好的
  7. c语言对n个数选择排序_选择排序_C语言「抄作业」
  8. 普华永道计算机在线测评题库,普华永道笔试题及经验
  9. 苹果ipad怎么刷机_苹果手机:iOS12刷机iOS12正式版刷机教程
  10. Wex5打包报错的解决办法
  11. java第八章习题,第八章 Servlet技术习题
  12. element table 左对齐
  13. dell r510服务器怎么装系统,DellR510安装系统.docx
  14. 百问网7天物联网记录(二)
  15. 基于国产银河飞腾多核 DSP +FPGA的图像识别硬件设计与算法实现
  16. 康卡斯特使持续升级,以有线电视
  17. Kbuild语法解析
  18. 文件下载---base64
  19. PPC WM6.1智能手机上使用日语辞典浅谈
  20. BQB 蓝牙无线技术

热门文章

  1. 2、oracle数据库的用户和权限
  2. Nacos(十二)之Java SDK
  3. 常用公有云接入——腾讯
  4. 汇编语言(二十三)之求一个数的补数
  5. <table/>默认适应内容宽度造成滚动条不显示的解决方法
  6. Java中关于String类型的10个问题
  7. Java对象内存结构
  8. SpringCloud服务安全连接
  9. Intellij IDEA 重置所有工具栏 Intellij IDEA 中的 Debug 控制台输出窗口不见了的解决办法
  10. 计算机网络协议和通信规则,计算机网络协议基本知识