Java应用程序的简单令牌认证

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

JSON Web令牌已Swift成为保护Web应用程序安全的标准,并取代了Cookie和会话等旧技术。 正确使用它们可以解决一系列安全问题,包括跨站点脚本攻击(XSS),中间人攻击(MITM)和跨站点请求伪造(CSRF)。 它们还为我们提供了可检查的元数据和强大的密码签名的好处。 在本文中,我将深入探讨JWT。 首先,我将介绍一些理论基础,解释它们如何工作。 之后,我将向您展示如何使用Okta配置Spring Boot应用程序以使用JWT身份验证。

JSON Web令牌是一个开放标准,并且有许多可用的库允许创建,验证和检查JWT。 您将使用Java JWT (又名JJWT),这是一个Java库,提供端到端JWT的创建和验证。 JJWT由Les Hazlewood创建, Les Hazlewood是Stormpath的前联合创始人兼CTO Apache Shiro的主要撰稿人,目前是Okta自己的高级架构师。 根据Apache 2.0许可,它是开源的。

了解JWT及其在身份验证中的作用

首先让我们研究一下authenticationtoken在这种情况下的含义。

身份验证证明用户就是他们所说的真实身份

令牌是一个独立的信息块。 它可能具有内在价值,也可能没有。 我将向您展示一种特定类型的令牌, 它确实具有内在价值,并通过会话ID解决了许多问题。

什么是JSON Web令牌? JWT是一种开放标准( RFC 7519 ),用于使用JSON在各方之间作为数字签名的字符串令牌传输信息。 可以使用HMAC算法或使用RSAECDSA的公用/专用密钥对对它们进行签名

换句话说:JWT是JSON令牌,是URL安全,紧凑且自包含的字符串。 通常,它们携带有关用户的已验证身份的信息。 它们通常经过编码和加密。 它们Swift成为网络上令牌实现的事实上的标准。 URL安全意味着令牌字符串可以在URL中使用,因为所有特殊字符都已被编码为简单的字母数字字符。 JWT也被认为是不透明的,因为字符串本身没有解码或解密就不会提供任何信息。

令牌通常被认为是一种授权机制,但是它们也可以用作在Web应用程序和服务器之间安全存储和传输信息的一种方式,与使用会话ID的方式非常相似。

将JWT与OAuth 2.0结合使用

许多OAuth 2.0实现都将JWT用于其访问令牌。 应该指出,OAuth 2.0和JWT规范是彼此完全独立的,彼此之间没有任何依赖关系。 将JWT用作OAuth 2.0的令牌机制会带来很多好处,如下所示。

无论使用哪种JWT实施,都必须将漂亮的Web令牌存储在某个地方。 Cookie和HTML5 Web存储是两个流行的选项。 两种选择都有好处和潜在的风险。 对此的讨论不在本文讨论范围之内,但是值得阅读上面提到的典型攻击:跨站点脚本攻击(XSS),中间人攻击(MITM)和跨站点请求伪造(CSRF)。 Okta使用HTML5网络存储。

无论将JWT存储在何处,都可以用JWT完全替换会话ID,并获得直接从会话ID / JWT访问元信息的额外好处。

看一下JWT的结构

那是很多首字母缩写词。 让我们看一下JWT。 在野外,JWT很害羞。 有些人甚至可能说他们太丑陋或无聊了(取决于您对206个字符串的感觉)。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vdHJ1c3R5YXBwLmNvbS8iLCJleHAiOjEzMDA4MTkzODAsInN1YiI6InVzZXJzLzg5ODM0NjIiLCJzY29wZSI6InNlbGYgYXBpL2J1eSJ9.43DXvhrwMGeLLlP4P4izjgsBB2yrpo82oiUPhADakLs

就像生活中的大多数事情一样,请不要凭空判断JWT(请记住,它们是不透明的)。 如果仔细看,您会发现字符串中有两个句点。 这些界定了JWT的不同部分:

  1. 标头
  2. 有效载荷/主体(或要求)
  3. 密码签名。
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.
eyJpc3MiOiJodHRwOi8vdHJ1c3R5YXBwLmNvbS8iLCJleHAiOjEzMDA4MTkzODAsInN1YiI6InVzZXJzLzg5ODM0NjIiLCJzY29wZSI6InNlbGYgYXBpL2J1eSJ9
.
43DXvhrwMGeLLlP4P4izjgsBB2yrpo82oiUPhADakLs

窥视令牌头

我知道我说过有些人认为JWT很无聊。 甚至不透明。 但是,如果您知道如何与他们交谈,JWT非常有趣。 让我们解码示例​​JWT并查看其中的内容。

标头只是通过Base64Url编码的。 它告诉我们令牌的类型和使用的哈希算法,通常是HMAC SHA256或RSA。

{"typ": "JWT","alg": "HS256"
}

顺便说一下, jsonwebtoken.io是用于编码和解码JWT的出色在线工具。

查看有效载荷

令牌的第二部分是有效负载声明

{"iss": "http://trustyapp.com/","exp": 1300819380,"sub": "users/8983462","scope": "self api/buy"
}

有效负载包含声明 。 声明是有关实体(通常是用户)和任何其他数据的声明。 索赔有以下三种:

  1. 已注册的声明: RFC 7519规范中定义的一组建议的声明。 一些示例是issexpaud
  2. 公共声明:可由令牌用户定义但应遵循命名约定以避免冲突的用户定义声明(应在IANA JSON Web令牌注册表中定义,或定义为包含抗冲突名称空间的URI),因为它们在公共命名空间中。
  3. 私人声明:用于在达成协议的各方之间共享信息的任意自定义声明(不必担心名称冲突,因为它们是私有的)。

在上面的示例中:

  • iss是发行令牌的人。 这是已注册的索赔。
  • exp是令牌过期的时间。 也是已注册的索赔。
  • 是主题。 通常是一个用户标识符。 也是已注册的索赔。
  • scope是OAuth 2.0常用的自定义私人声明。

范围声明通常用于提供授权信息。 例如,让应用程序知道用户有权访问应用程序的哪一部分。 当然,这并不能免除服务器执行自己的授权检查的责任。 Web应用程序安全性的一般原则是冗余。 客户端应用程序提供一个检查点,服务器提供另一个检查点。

JSON数据经过Base64URL编码以创建编码的有效负载。 编码的标头和有效负载用于创建签名。

检查令牌签名

签名是JWT结构的最后一部分。 它获取标头,然后有效负载向哈希算法添加一个秘密,并吐出与JWT其余部分中未更改的数据相对应的哈希。 使用签名,客户端应用程序和服务器可以验证它们接收的令牌是原始的,未更改的令牌。

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret
)

了解此签名不提供机密性是非常重要的。 此信息是公开可见的。 签名保证令牌未被篡改,但不会隐藏数据(小孩可以在叔叔的iPhone 4上解码Base64)。 如果要发送敏感信息,必须对JWT进行加密。

通常以从属权利要求的形式存储用户标识符的做法。 当JWT签名时,它称为JWS。 加密后,称为JWE。

无国籍是JWT的一大好处。 服务器不需要存储任何会话数据。 它可以全部存储在令牌中,并在应用程序和服务器之间来回传递。 这看似是一个奇怪的电子飞盘游戏,但此模型的伸缩性很好(只要会话状态相对较小,它应该确实如此)。 从JWT解码会话状态要比在每个请求上访问数据库仅从会话存储中检索一些基本用户状态信息快得多,并且性能更高。

使用Java创建和验证JWT

我已经提到过我们的JJWT项目吗? 查看其GitHub页面 。 这是针对Java的完全开源的JWT解决方案。

让我们看一个使用JJWT创建JWT的示例。

import io.jsonwebtoken.Jwts;  
import io.jsonwebtoken.SignatureAlgorithm;  byte[] key = getSignatureKey();  String jwt = Jwts.builder().setIssuer("http://trustyapp.com/")  .setSubject("users/1300819380")  .setExpiration(expirationDate)  .put("scope", "self api/buy")  .signWith(SignatureAlgorithm.HS256,key)  .compact();

该库使用了流畅的Builder API。 请注意用于设置声明的设置器。 标准声明具有预定义的设置器,例如setSubject("users/1300819380") ,而自定义声明使用键值put()方法。 例如范围声明, put("scope", "self api/buy")

验证JWT一样容易。

String subject = "HACKER";  try {  Jws jwtClaims = Jwts.parser().setSigningKey(key).parseClaimsJws(jwt);  subject = claims.getBody().getSubject();  // OK, you can trust this JWT  
} 
catch (SignatureException e) {  // don't trust this JWT!  
}

如果对JWT进行了任何篡改,则解析声明将引发SignatureException并且subject变量的值将保持HACKER 。 如果它是有效的JWT,则将从中提取subjectclaims.getBody().getSubject()

了解OAuth 2.0以Java进行令牌身份验证

稍后,您将使用Okta的OAuth 2.0实现来创建Spring Boot应用程序。 但是首先,您应确保了解什么是OAuth,什么不是OAuth。

简而言之,OAuth 2.0是“授权的行业标准协议”(来自OAuth.net网站 )。 授权意味着它为应用程序提供了一种方法,以确保用户有权执行操作或访问资源。 OAuth 2.0 不提供用于验证用户身份的工具。

那是身份验证。

还有另一个称为OpenID Connect或OIDC的协议层,通常与提供身份验证的OAuth 2.0配对。 OIDC建立在OAuth 2.0的基础上,并提供一种验证用户身份的方法,通常是让用户使用用户名和密码登录,或者使用许多社交登录选项之一。 因为OIDC 确实与OAuth 2.0一起验证用户的身份,所以它们一起为Web应用程序和服务器提供了完整的身份验证和授权协议。

记得:

  • OIDC是身份验证,还是我是谁?
  • OAuth是授权,还是该怎么办?

在Java中配置Okta OIDC应用程序以进行令牌认证

很快,您将像专家一样生成和验证JWT。 但是首先,您需要转到developer.okta.com并创建一个OpenID Connect(OIDC)应用程序。 如果尚未注册免费的开​​发者帐户。 我是否提到过它完全免费?

登录到Okta开发人员仪表板。 转到应用程序 ,然后单击添加应用程序按钮。

选择Web应用程序类型,然后单击“ 下一步”

令牌认证

在下一页上,您需要给新应用程序起一个易记的名称。 您可以随意命名。 您还需要选中“ 客户端凭据”复选框。 这将激活您将要使用的client_credentials授予类型。

令牌认证

单击完成

请注意下一页底部的客户端ID客户端密钥 。 稍后您将需要这些。

令牌认证

安装HTTPie

我们将使用一个很棒的命令行实用工具来运行一些示例:HTTPie。 如果尚未安装,请访问其网站并安装。

申请JWT

时机已到。 我知道你很兴奋 您终于要见识JWT。

我知道您很想离开,但是您还需要执行一个初步的步骤。 您需要对上述Okta OIDC应用程序中的客户端ID和客户端密钥进行编码,以便在HTTP基本授权标头中使用。

通用格式为:

Authorization: Basic Base64Encode(< your client id >:< your client secret >)

注意中间的: 。 获取您的客户ID,并使用冒号将其加入到您的客户秘密中。 Base64对结果字符串进行编码(提示:使用base64encode.org )。 然后将其包含在您的请求中。 它看起来像这样:

Authorization: Basic ABChZzU4NDg5YW1aTDCBCB4waDc6TUp3YWN4RU5WNzQ1bEdQNWJPdlFETV9iaDE5NGp1eHQ3SXJfdWEzQQ==

互联网上有各种实用程序可以为您完成此任务。 尽管这些对于教程和从头开始开发可能会有所帮助,但出于显而易见的原因,但使用它们来编码生产凭证并不是一个好主意。

接下来,您需要的是Okta OIDC应用程序的令牌请求URL。 这将是您的Okta授权服务器基本URL加/v1/token 。 从顶部菜单转到API ,然后选择“ 授权服务器” 。 查看默认服务器的Issuer URI 。 添加/v1/token

例如,类似于: https://{yourOktaDomain}/oauth2/default/v1/token

使用HTTPie,您的终端命令将如下所示:

http -f POST https://{yourOktaDomain}/oauth2/default/v1/token \
'Authorization: Basic MG9hZzU4NDg5YW1aTDBNRU4wa...' \
grant_type=client_credentials

这里发生了什么?

-f是表单标志。 Content-Type设置为application/x-www-form-urlencoded; charset=utf-8 application/x-www-form-urlencoded; charset=utf-8并使用key=value表示法分析命令行以获取表单数据。

POST是HTTP请求类型。

https://{yourOktaDomain}/oauth2/default/v1/token是令牌请求URL。

'Authorization: Basic ...'设置基本auth标头。

grant_type=client_credentials是一个表单值,它告诉Okta我们正在请求的授予类型。 一秒钟内将对此进行更多介绍。

如果运行此命令,请继续! –您将收到invalid scope错误。

HTTP/1.1 400 Bad Request
Cache-Control: no-cache, no-store
Connection: close
Content-Type: application/json;charset=UTF-8
...{"error": "invalid_scope","error_description": "The authorization server resource does not have any configured default scopes, 'scope' must be provided."
}

使用client_credentials授予类型实际上只是一种方便。 这是一种授予类型,它使我们无需遵循浏览器重定向即可请求JWT。 client_credentials通常用于API交互。

根据OAuth规范 ,“客户端使用客户端凭据授予类型来获取用户上下文之外的访问令牌。 客户端通常使用它来访问有关其自身的资源,而不是访问用户的资源。”

将Okta用作单一登录提供程序(一种更常见的用例)时,可以使用“ 授权代码授予” 。 这种授予类型(其中应用程序允许用户登录并交换访问令牌的授权代码),但是需要一系列重定向,而这些重定向将很难从命令行客户端(例如HTTPie)进行管理。 因此,本教程使用“客户端证书”授予类型来方便地演示一些基本的OAuth / JWT功能。

您希望能想到:“好极了,但是范围误差呢?”

很高兴你问!

范围提供了一种定义和限制令牌授予的访问权限的方法。 在对用户进行授权和身份验证时,通常会使用一系列范围,例如openid email profile 。 这些作用域告诉服务器,该应用程序希望访问用户的个人资料,电子邮件地址,并希望发出OpenID身份验证请求。

客户证书授予类型要求我们定义一个自定义范围。 这就是invalid scope错误所抱怨的。

让我们修复它!

添加自定义范围

返回至developer.okta.com 。 在顶部菜单中,转到API授权服务器

从服务器列表中单击默认服务器。

单击“ 作用域”选项卡,然后单击“ 添加作用域”按钮。

将范围命名为“ customScope”,对其进行描述,然后单击“ 创建” 。 您需要匹配的名称,但是描述是任意的。

令牌认证

再次运行令牌请求

重新运行请求,这次使用自定义范围。

http -f POST https://{yourOktaDomain}/oauth2/default/v1/token \
'Authorization: Basic MG9hZzU4NDg5YW1aTDBN...' \
grant_type=client_credentials \
scope=customScope

这次您将获得令牌!

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store
Connection: Keep-Alive
Content-Type: application/json;charset=UTF-8
Pragma: no-cache
...
{"access_token": "eyJraWQiOiJldjFpay1DS3UzYjJXS3QzSVl1MlJZc3...","expires_in": 3600,"scope": "customScope","token_type": "Bearer"
}

注意Cache-ControlPragma标头。 您不希望此响应被缓存在任何地方。 access_token是浏览器在后续请求中将使用的内容。 请记住,不需要将JWT用作OAuth 2.0访问令牌。 它们非常方便,因为您可以在其中编码防篡改(并且可能是机密的)元数据。

使用您的访问令牌

要在请求中包含访问令牌,请使用类型为BearerAuthorization标头。 下面是一个示例GET请求。

GET /admin HTTP/1.1
Authorization: Bearer eyJraWQiOiJldjFpay1DS3UzYjJXS3QzSVl1MlJZc3...

输入Spring Boot以使用Java进行令牌认证

您准备好使用Java吗? 我已经准备好使用Java。

您要做的第一件事是从GitHub存储库克隆我们的示例应用程序 。

现在,使用以下终端命令检出start分支:

git clone -b start https://github.com/oktadeveloper/okta-spring-boot-token-auth-example.git

此应用程序非常简单。 至少,它看起来超级简单。 实际上,在后台,Spring Boot和Okta做出了相当大的努力,以为您提供功能齐全的REST资源服务器,该服务器具有使用OAuth 2.0和Okta OIDC应用程序进行的JWT令牌身份验证的功能。 AM!

唯一需要进行的配置是在src/main/resources/application.yml文件中。 您需要从上面创建的几个步骤的Okta OIDC应用程序中填写您的客户端ID客户端密钥 。 您使用这些来生成令牌。 它们大致(如果是斜视,则有点类似)对应于OIDC应用程序的用户名和密码。

server:  port: 8080  okta:  oauth2: issuer: https://{yourOktaDomain}/oauth2/default  clientId: {yourClientId}clientSecret: {yourClientSecret}

这就是您需要做的! 至此,您已经拥有了一个功能齐全(如果不是很令人兴奋的话)的Spring Boot资源服务器。

该应用程序的入口点位于Application.java文件中:

@EnableResourceServer  
@SpringBootApplication  
public class Application {  public static void main(String[] args) {  SpringApplication.run(Application.class, args);  }
}

您会注意到这是老式的main()方法所在的地方。 这些天感觉有点像遗物,但这就是所有魔力的开始。 在每个愚蠢的猫录像和Facebook激烈的政治辩论背后,都有一个main()方法开始了这一切。

您正在使用SpringApplication.run()方法来引导Spring框架,该框架将加载Application类。 这将拾取@EnableResourceServer@SpringBootApplication批注。 @SpringBootApplication告诉Spring加载Spring Boot。 @EnableResourceServer将Spring Boot应用程序配置为通过OAuth令牌(可能与OAuth 2.0单一登录相对)对请求进行身份验证。

@EnableResourceServer有几个含义,值得指出。 如果您看一下有关注释的文档 ,则会看到几个要点:如果要配置资源服务器,则需要定义ResourceServerConfigurerAdapter bean; 并以3的硬编码顺序添加了WebSecurityConfigurerAdapter bean。

你为什么要在乎呢? 因为在更复杂的Web应用程序中,您将要同时使用ResourceServerConfigurerAdapterWebSecurityConfigurerAdapter来配置权限。 与使用@EnableOAuth2Sso批注时所做的WebSecurityConfigurerAdapter ,这与简单地使用WebSecurityConfigurerAdapter @EnableOAuth2Sso ,所以我想警告您。 通常,资源服务器端点将以/api或其他内容开头,并由ResourceServerConfigurerAdapter进行配置和保护,而其他任何纯HTML端点将由WebSecurityConfigurerAdapter进行配置。 但是,您需要将@Order(Ordered.HIGHEST_PRECEDENCE)添加到WebSecurityConfigurerAdapter以使其优先于具有硬编码顺序的默认顺序。

如果要查看如何完成此操作的更具体示例,请查看full-config分支 。 您也可以在最后的链接中浏览Siva Tech文章。

除了这些,让我们看一下HelloController类。

@RestController
public class HelloController {  @RequestMapping("/")  public String home(java.security.Principal user) {  return "Hello " + user.getName();  }
}

@RestController批注是@Controller@ResponseBody批注的组合。

@Controller告诉Spring Boot此类是控制器类,并查找URL请求到内部方法的映射。

@ResponseBody指示控制器方法返回原始响应数据,并且不映射到模板名称。 这就是它返回简单字符串的方式,而不是使用Spring的模型和视图模板系统。

@RequestMapping("/")表示将home()方法映射到基本URL。

注意使用了依赖注入来获取java.security.Principal 。 这项工作需要大量自动调整。 Spring和Okta会根据OAuth 2.0和OpenID Connect规范共同验证令牌并进行来回通信,对用户进行身份验证,并提供JWT授权令牌,该令牌包含具有用户“名称”的元数据。

运行Spring Boot App

好的。 一起让它成为现实!

使用以下命令运行Spring Boot应用程序: ./gradlew bootRun

您应该看到很多文本以如下形式结尾:

...
[main] INFO org.springframework.jmx.export.annotation.AnnotationMBeanExporter - Registering beans for JMX exposure on startup
[main] INFO org.springframework.boot.web.embedded.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''
[main] INFO com.okta.springboottokenauth.Application - Started Application in 21.209 seconds (JVM running for 21.709)
[2018-10-11 10:31:58.646] - 22235 INFO [http-nio-8080-exec-1] --- org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/]: Initializing Spring FrameworkServlet 'dispatcherServlet'
[http-nio-8080-exec-1] INFO org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcherServlet': initialization started
[http-nio-8080-exec-1] INFO org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcherServlet': initialization completed in 13 ms

使用JWT进行身份验证

现在运行Spring Boot应用程序,使用HTTPie运行不带令牌的GET请求:

http GET http://localhost:8080

您将获得401 /未经授权:

HTTP/1.1 401
Cache-Control: no-store
Content-Type: application/json;charset=UTF-8
...
{"error": "unauthorized","error_description": "Full authentication is required to access this resource"
}

重新运行它,这次包括您的令牌(取决于经过了多少时间,您可能需要请求一个新令牌):

http GET :8080 'Authorization: Bearer eyJraWQiOiJldjFpay1DS3UzYjJXS3QzSVl1...'

提示:如果收到显示“ Invalid JOSE Header kid”的invalid_token错误,则很有可能用不正确的值更新了application.yml

假设您的令牌仍然有效,您将获得一个HTTP 200:

HTTP/1.1 200
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 26
Content-Type: text/plain;charset=UTF-8
...Hello 0oag58489amZL0MEN0h7

0oag58489amZL0MEN0h7将是您的客户ID。

请记住,您使用的是client_credentials授予类型,并且已将客户端ID客户端密钥作为凭据发送给服务器。 因此,授权服务器将您的客户ID作为您的“名称”发送回去。 在不同的情况下,例如使用授权码授予,这将是用户的名称(或者可能是他们的电子邮件地址或用户名)。

了解有关使用Java进行令牌身份验证和构建安全应用程序的更多信息

了解令牌身份验证对于构建现代Web应用程序至关重要。 有两种用于签名和加密令牌的主要方法:哈希和公钥/私钥。 两种方法都是互联网安全的基础。 在HMAC上查看Wikipedia页面 ,以继续学习JWT中使用的基于哈希的消息认证代码(HMAC)。 要了解公共/专用密钥加密, Red Hat进行了出色的介绍 。

一旦您对这两种技术真正感到满意,就可以看一下关于Medium的有关JWT的出色教程 。

您可能还需要查看RFC规范 。

在Spring结束时,我发现Siva Tech Lab的本教程对说明如何使用OAuth 2.0实施Spring Boot应用程序很有帮助。

以下是Okta博客的其他一些链接,可帮助您继续前进:

  • Spring Boot,OAuth 2.0和Okta入门
  • 确保Spring Boot应用程序安全的10种绝佳方法
  • 如果您的JWT被盗怎么办?
  • 使用Spring Boot 2.0和OAuth 2.0构建并保护微服务

如果您对此帖子有任何疑问,请在下面添加评论。 有关更多精彩内容, 请在Twitter上关注@oktadev , 在Facebook上关注我们,或订阅我们的YouTube频道 。

Java Apps的简单令牌身份验证最初于2018年10月16日发布在Okta开发人员博客上。

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

翻译自: https://www.javacodegeeks.com/2018/10/simple-token-authentication-java-apps.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346307.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

element手机验证格式_基于Vue+elementUI实现动态表单的校验功能(根据条件动态切换校验格式)...

前言开发过程中遇到了一个需求&#xff0c;根据用户选择的联系方式&#xff0c;动态改变输入框的检验条件&#xff0c;并且整个表单是可以增加的在线访问:动态表单校验github(欢迎star): https://github.com/Mrblackant. ..思考几个问题1.整个表单是可新增的&#xff0c;所以要…

matlab中rb代表什么意思,你知道“川藏线上”女游客举着“求RB”的牌子是啥意思吗?暗语啊!...

现在穷游好像一种旅行圈的时髦&#xff0c;很多人都想着穷游能够锻炼人的意志&#xff0c;能够促进人与人的交流与合作&#xff0c;能够在路上遇到不一样的精彩&#xff0c;能够发现人性与真善美。现在穷游的人不在少数&#xff0c;尤其是在川藏线上&#xff0c;想要穷游入藏的…

vscode 智能打印_vscode智能提示

vscode智能提示官方版支持部分的语法高亮&#xff0c;现在官方C插件更新比较快&#xff0c; Visual Studio for C / C代码的扩展增加了C / C在Visual Studio语言支持。vscode智能提示功能介绍语言服务代码格式(铛格式)自动完成(实验)符号搜索转到定义/声明查看定义/声明类/方法…

重节点差商matlab,数值分析佳习题(含答案).doc

数值分析佳习题(含答案)2008信息与计算科学专业计算方法习题参考解答 江世宏编PAGEPAGE 25第一章 绪论姓名 学号 班级习题主要考察点&#xff1a;有效数字的计算、计算方法的比较选择、误差和误差限的计算。1 若误差限为,那么近似数0.003400有几位有效数字&#xff1f;(有效数字…

matlab 柴油机仿真,用MATLAB/SIMULINK实现柴油机及其控制系统的动态仿真

第 16卷(1998)第 3期 内 燃 机 学 报 Transaetions of CSICE VDl_16(1998)No&#xff0e;3 ④ f 用 MATLAB&#xff0f;SIMULINK 实现 柴油机 及其控制系统的动态仿真 980045 细描 述 了空气流量 率、燃 空 比、指 示热 效率、摩擦损 失、平均指 示 压力输 出、发 动 机 动力 学…

华为主题锁屏壁纸换不掉_华为手机总多出莫名的照片?那是因为这3个设置没关闭,赶紧自查...

随着华为在科技、5G以及数码领域的表现越来越好&#xff0c;使用华为手机的人也越来越多。不知道你在使用华为手机的过程中&#xff0c;有没有这样的感觉&#xff0c;华为手机总是多出莫名其妙的照片&#xff0c;即使删除了下次还会出现。如果有这样的情况&#xff0c;可能是手…

tomcat 正常关闭_Tomcat的带有守护程序和关闭钩子的正常关闭

tomcat 正常关闭我的最后两个博客讨论了长时间轮询和Spring的DeferredResult技术&#xff0c;并且为了展示这些概念&#xff0c;我将我的Producer Consumer项目中的代码添加到了Web应用程序中。 尽管该代码演示了博客所提出的观点&#xff0c;但其逻辑上确实包含大量漏洞。 除了…

php nginx 域名重定向,Nginx默认虚拟主机、用户认证、域名重定向

Nginx默认虚拟主机定义默认虚拟主机配置文件,在http下面加入include vhost/*.conf在/usr/local/nginx/conf/下创建目录#mkdir vhost/ //创建vhost目录#cd vhost/ //进入目录#vim aaa.com.conf //编辑文件server{listen 80 default_server; // 有这个标记的就是默认虚拟主机serv…

Java:使用SingletonStream获得性能

仅具有一个元素的Java流有时会在应用程序中造成不必要的开销。 了解如何使用SingletonStream对象并为其中某些此类流获得十倍的性能&#xff0c;并了解如何同时简化代码。 背景 Java 8中的Stream库是有史以来Java语言最强大的功能之一。 一旦您开始了解它的多功能性和所产生的…

多元线性回归分析spss结果解读_多元线性回归分析理论详解及SPSS结果分析

当影响因变量的因素是多个时候&#xff0c;这种一个变量同时与多个变量的回归问题就是多元回归&#xff0c;分为&#xff1a;多元线性回归和多元非线性回归。这里直说多元线性回归。对比一元线性回归&#xff1a;1.1多元回归模型&#xff1a;1.2多元回归方程1.3估计的多元回归方…

gilab无法解析php文件,gitlab重新设置域名后就无法访问了。

gitlab-ctl status ,查看是nignx启动不成功。查看gitlab-ctl tail日志&#xff0c;一直报这个错误 &#xff1a;> /var/log/gitlab/nginx/current <2020-01-06_09:12:15.16681 /opt/gitlab/embedded/sbin/nginx: error while loading shared libraries: libutility_mini_…

nginx请求转发被拒绝_nginx反向代理(请求转发-URL匹配规则)

反向代理适用于很多场合&#xff0c;负载均衡是最普遍的用法。nginx 作为目前最流行的web服务器之一&#xff0c;可以很方便地实现反向代理。当在一台主机上部署了多个不同的web服务器&#xff0c;并且需要能在80端口同时访问这些web服务器时&#xff0c;可以使用 nginx 的反向…

php调用pdf2html,php html2pdf

*安装composer运行html2pdf时&#xff0c;readme里面建议按照composer-setup.exe安装过程中出现openssl的问题&#xff0c;在php.ini中开启相应extension即可&#xff0c;路径写绝对路径&#xff0c;否则按默认路径找不到在html2pdf的文件路径下&#xff0c;cmd运行composer in…

electron 打开调试_Electron 应用调试指南

Electron 是一个基于 Node.js 和 Chromium 的开源框架&#xff0c;用于构建桌面应用&#xff0c;开发者可以使用 web 技术(HTML&#xff0c;JavaScript 和 CSS)完成整个应用的开发。许多知名桌面应用基于 Electron 实现&#xff0c;如 VSCode&#xff0c;Slack 和 GitHub Deskt…

java中方法的命名_Java方法中的参数太多,第5部分:方法命名

java中方法的命名在上一篇文章 &#xff08;有关处理Java方法中过多参数的系列文章的 第4部分 &#xff09;中&#xff0c;我将方法重载视为一种向客户提供需要较少参数的版本的方法或构造函数的方法。 我描述了该方法的一些缺点&#xff0c;并建议从方法重载中摆脱出来以使用不…

oracle lms进程 内存,Oracle RAC 内存融合(Cache Fusion)

原标题&#xff1a;Oracle RAC 内存融合(Cache Fusion)内存融合核心进程LMS(Global Cache Service Process)&#xff1a;这个进程负责完成GCS的大部分工作&#xff0c;它会维护GRD中数据块资源的信息&#xff0c;完成数据块在实例之间的传递工作&#xff0c;相关消息的发送和接…

sougou ubuntu 优麒麟_搜狗输入法 Linux – V2.3 版发布,完美适配优麒麟 19.10

搜狗输入法 Linux – V2.3 版发布&#xff0c;完美适配优麒麟 19.10fenshezhuiyi2 2019年10月19日 暂无评论 阅读 4,346 次昨天已发布优麒麟操作系统 19.10 版本&#xff0c;该版本集成了全新的控制面板和软件商店&#xff0c;不知道大家是否已下载体验。今天小编要为大家介绍一…

oracle多条sql语句常量,如何在Oracle中一次执行多条sql语句

有时我们需要一次性执行多条sql语句&#xff0c;而用来更新的sql是根据实际情况用代码拼出来的解决方案是把sql拼成下面这种形式&#xff1a;beginupdate TB_VG set seq 1, vessel_id Jin14, vessel_type TRACK where batch_number 20837 and train_id 0233086;update TB_…

JDK 11:新的默认收集方法toArray(IntFunction)

“ JDK 11 Early-Access发行说明 ”表明JDK 11的Early Access Build 20在Collection接口上包括一个新的默认方法 &#xff0c;该方法 “允许将集合的元素转移到所需运行时类型的新创建的数组中”。 这个新的默认方法 [ Collection.toArray&#xff08;IntFunction&#xff09; …

获取清空textarea的文字内容_运用|你会做 词云图(文字云) 吗?

词云图,也叫文字云,是对文本中出现频率较高的“关键词”予以视觉化的展现,词云图过滤掉大量的低频低质的文本信息,使得浏览者只要一眼扫过文本就可领略文本的主旨。今天&#xff0c;兰色就分享一下词云图的做法。制作步骤&#xff1a;1、打开词云图网站打开网页https://wordart…