建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

2016年5月12日更新:构建Java应用程序? JJWT是一个Java库,由我们自己的Les Hazlewood开发,提供端到端JWT的创建和验证。 JJWT永久免费且开源(Apache许可证,版本2.0),易于使用和理解。 它的设计采用了以构建者为中心的流畅界面,从而掩盖了其大部分复杂性。 我们希望您能尝试一下 ,并告诉我们您的想法! (并且,如果您是Node开发人员,请查看NJWT !)

在我的上一篇文章中 ,我们涵盖了很多基础,包括我们传统上如何保护网站安全,使用cookie和会话的一些陷阱以及如何通过传统方式解决这些陷阱。

在本文中,我们将超越传统,深入探讨如何使用JWT(JSON Web令牌)进行令牌身份验证,不仅解决了这些问题,而且还为我们提供了可检查的元数据和强大的加密签名的好处。

救援的令牌认证!

首先让我们检查一下在这种情况下authenticationtoken含义。

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

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

JSON Web令牌(JWT)

JWT是URL安全,紧凑,自包含的字符串,其中包含有意义的信息,这些信息通常经过数字签名或加密。 它们正Swift成为网络上令牌实施的实际标准。

URL安全是一种说法,可以说整个字符串都已编码,因此没有特殊字符,并且令牌可以放入URL中。

该字符串是不透明的,可以与使用会话ID几乎相同的方式独立使用。 不透明是指查看字符串本身没有提供任何其他信息。

但是,还可以对字符串进行解码以提取元数据,并且可以对签名进行加密验证,以使您的应用程序知道令牌未被篡改。

JWT和OAuth2访问令牌

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

JWT可以存储在cookie中,但是我们之前讨论的cookie的所有规则仍然适用。 您可以将会话ID完全替换为JWT。 然后,您可以获得直接从该会话ID访问元信息的额外好处。

在野外,它们看起来就像是另一个丑陋的弦:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vdHJ1c3R5YXBwLmNvbS8iLCJleHAiOjEzMDA4MTkzODAsInN1YiI6InVzZXJzLzg5ODM0NjIiLCJzY29wZSI6InNlbGYgYXBpL2J1eSJ9.43DXvhrwMGeLLlP4P4izjgsBB2yrpo82oiUPhADakLs

如果仔细看,您会发现字符串中有两个句点。 这些意义重大,因为它们界定了JWT的不同部分。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.
eyJpc3MiOiJodHRwOi8vdHJ1c3R5YXBwLmNvbS8iLCJleHAiOjEzMDA4MTkzODAsInN1YiI6InVzZXJzLzg5ODM0NjIiLCJzY29wZSI6InNlbGYgYXBpL2J1eSJ9
.
43DXvhrwMGeLLlP4P4izjgsBB2yrpo82oiUPhADakLs

JWT结构

JWT具有三部分结构,每个部分都是base64编码的:

以下是解码的部分:

标头

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

索偿

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

密码签名

tß´—™à%O˜v+nî…SZu¯µ€U…8H×

智威汤逊索赔

让我们检查索赔部分。 可以在此处找到属于JWT规范的每种声明。

iss是发行令牌的人。
exp是令牌过期的时间。
sub是令牌的主题。 这通常是某种用户标识符。

权利要求的以上部分全部包含在JWT规范中。 scope未包含在规范中,但通常用于提供授权信息。 也就是说,用户可以访问应用程序的哪些部分。

JWT的优点之一是,可以将任意数据编码到上述scope的权利要求中。 另一个优点是,客户端现在可以对该信息做出反应,而无需与服务器进行任何进一步的交互。 例如,可以基于在scope权利要求中找到的数据来隐藏页面的一部分。

注意 :服务器始终验证客户机执行的操作仍然很关键,也是最佳实践。 例如,如果在客户端上执行了某些管理操作,则您仍想在应用程序服务器上验证当前用户是否有权执行该操作。 您永远不会仅依赖客户端授权信息。

您可能已经获得了另一个优势:加密签名。 签名可以被验证,证明JWT未被篡改。 请注意,密码签名的存在并不保证机密性。 仅当对JWT进行加密签名时,才能确保机密性。

现在,最重要的是: 无国籍 。 尽管服务器将需要生成JWT,但是它不需要将其存储在任何地方,因为所有用户元数据都已直接编码到JWT中。 服务器和客户端可以来回传递JWT,而从不存储它。 这样可以很好地扩展。

管理承载令牌安全性

隐式信任是一种折衷。 这些类型的令牌通常称为Bearer令牌,因为获得对应用程序受保护部分的访问所需的全部就是有效的未过期令牌的表示。

您必须解决以下问题:令牌应使用多长时间? 您将如何撤销它? (还有其他整篇文章可以针对刷新令牌进行 。)

如果未加密,则必须注意存储在JWT中的内容。 不要存储任何敏感信息。 以sub权利要求的形式存储用户标识符是一种普遍接受的做法。 当JWT签名时,它称为JWS。 加密后,称为JWE。

Java,JWT和您!

我们为Github上的JJWT项目感到自豪。 它是由Stormpath的首席技术官Les Hazlewood最初撰写的,它是针对Java的完全开源的JWT解决方案。 它是最容易使用和理解的库,用于在JVM上创建和验证JSON Web令牌。

您如何创建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();

首先要注意的是用于创建JWT的流畅的 Builder API。 方法调用被链接在一起,最终以compact调用返回最终的JWT字符串。

还要注意,当我们设置规范中的一项权利要求时,我们使用了二传手。 例如: .setSubject("users/1300819380") 。 设置自定义声明后,我们会使用调用来放置并指定键和值。 例如: .put("scope", "self api/buy")

验证JWT一样容易。

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

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

什么是OAuth?

在下一节中,我们将看一个使用Stormpath的OAuth2实现的示例,该实现利用了JWT。

OAuth2规范周围有很多困惑。 那部分是因为它确实是über规范–它具有很多复杂性。 这也是因为OAuth1.a和OAuth2是非常不同的野兽。 我们将看一看OAuth2规范的一个非常具体,易于使用的子集。 我们有一篇很棒的文章,它详细介绍了什么是OAuth 。 在这里,我们将提供一些简短的背景知识,然后直接进入示例。

OAuth2基本上是一种支持授权工作流程的协议。 这意味着它为您提供了一种确保特定用户有权执行某项操作的方法。

而已。

OAuth2 并不旨在执行诸如验证用户身份的工作, 而是由身份验证服务负责。 身份验证是在验证用户身份( 例如要求输入用户名/密码 )时进行的验证,而授权是在检查现有用户已拥有的权限时进行的验证。

请记住,OAuth2是授权协议。

使用OAuth授权类型进行授权

让我们看一下典型的OAuth2交互。

POST /oauth/token HTTP/1.1
Origin: https://foo.com
Content-Type: application/x-www-form-urlencodedgrant_type=password&username=username&password=password

grant_typegrant_type 。 这种交互类型也需要application/x-www-form-urlencoded内容类型。 假设您通过网络传递用户名和密码,则始终希望连接是安全的。 不过,好消息是,响应将具有OAuth2承载令牌。 然后,此令牌将用于以后浏览器与服务器之间的每次交互。 这里有一个非常简短的介绍,其中用户名和密码是通过网络传递的。 假设服务器上的身份验证服务验证了用户名和密码,则响应如下:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache{"access_token":"2YotnFZFEjr1zCsicMWpAA...","token_type":"example","expires_in":3600,"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA...","example_parameter":"example_value"
}

注意Cache-ControlPragma标头。 我们不希望此响应被缓存在任何地方。 access_token是浏览器在后续请求中将使用的内容。 同样,OAuth2和JWT之间没有直接关系。 但是, access_token可以是JWT。 这就是编码的元数据的额外好处所在。这是在以后的请求中利用访问令牌的方式:

GET /admin HTTP/1.1
Authorization: Bearer 2YotnFZFEjr1zCsicMW...

Authorization标头是标准标头。 使用OAuth2不需要自定义标头。 在这种情况下,类型是Bearer而不是Basic类型。 访问令牌直接包含在Bearer关键字之后。 这样就完成了密码授予类型的O​​Auth2交互。 浏览器的每个后续请求都可以使用Authorizaion: Bearer标头和访问令牌。

还有另一种称为client_credentials授予类型,它使用client_idclient_secret而不是usernamepassword 。 此授予类型通常用于API交互。 尽管客户ID和秘密机密的功能类似于用户名和密码,但它们通常具有更高的质量安全性,并且不一定是人类可读的。

带我们回家:OAuth2 Java示例

我们到了! 现在该深入研究一些演示JWT的特定代码了。

Spring Boot Web MVC

Stormpath Java SDK中有许多示例。 在这里,我们将看一个Spring Boot Web MVC示例。 这是示例中的HelloController :

@RestController
public class HelloController {@RequestMapping("/")String home(HttpServletRequest request) {String name = "World";Account account = AccountResolver.INSTANCE.getAccount(request);if (account != null) {name = account.getGivenName();}return "Hello " + name + "!";}}

为了演示的目的,关键是:

Account account = AccountResolver.INSTANCE.getAccount(request);

在幕后,仅当存在经过身份验证的会话时, account才会解析为Account对象(而不是null )。

生成并运行示例代码

要构建并运行此示例,请执行以下操作:

☺ dogeared jobs:0 ~/Projects/StormPath/stormpath-sdk-java (master|8100m)
➥ cd examples/spring-boot-webmvc/
☺ dogeared jobs:0 ~/Projects/StormPath/stormpath-sdk-java/examples/spring-boot-webmvc (master|8100m)
➥ mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Stormpath Java SDK :: Examples :: Spring Boot Webapp 1.0.RC4.6-SNAPSHOT
[INFO] ------------------------------------------------------------------------... skipped output ...[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.865 s
[INFO] Finished at: 2015-08-04T11:46:05-04:00
[INFO] Final Memory: 31M/224M
[INFO] ------------------------------------------------------------------------
☺ dogeared jobs:0 ~/Projects/StormPath/stormpath-sdk-java/examples/spring-boot-webmvc (master|8100m

启动Spring Boot示例

然后,您可以像这样启动Spring Boot示例:

☺ dogeared jobs:0 ~/Projects/StormPath/stormpath-sdk-java/examples/spring-boot-webmvc (master|8104m)
➥ java -jar target/stormpath-sdk-examples-spring-boot-web-1.0.RC4.6-SNAPSHOT.jar.   ____          _            __ _ _/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/  ___)| |_)| | | | | || (_| |  ) ) ) )'  |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::        (v1.2.1.RELEASE)2015-08-04 11:51:00.127  INFO 17973 --- [           main] tutorial.Application                     : Starting Application v1.0.RC4.6-SNAPSHOT on MacBook-Pro.local with PID 17973 ... skipped output ...2015-08-04 11:51:04.558  INFO 17973 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-08-04 11:51:04.559  INFO 17973 --- [           main] tutorial.Application                     : Started Application in 4.599 seconds (JVM running for 5.103)

注意 :这假设您已经设置了一个Stormpath帐户,并且您的api密钥位于~/.stormpath/apiKey.properties 。 在此处查找有关使用Spring Boot快速设置Stormpath的更多信息。

使用JSON Web令牌进行身份验证(或不进行身份验证)

现在,我们可以练习该示例,并展示一些实际应用中的JWT! 首先,在没有任何身份验证的情况下命中端点。 我喜欢使用httpie ,但是任何命令行http客户端都可以。

➥ http -v localhost:8080
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/0.9.2HTTP/1.1 200 OK
Accept-Charset: big5, big5-hkscs, cesu-8, euc-jp, euc-kr, gb18030, ...
Content-Length: 12
Content-Type: text/plain;charset=UTF-8
Date: Tue, 04 Aug 2015 15:56:41 GMT
Server: Apache-Coyote/1.1Hello World!

-v参数产生详细的输出,并显示请求和响应的所有标头。 在这种情况下,输出消息就是: Hello World! 。 这是因为没有建立的会话。

使用Stormpath OAuth端点进行身份验证

现在,让我们点击oauth端点,以便我们的服务器可以使用Stormpath进行身份验证。 您可能会问,“什么是oauth端点?” 上面的控制器未指示任何此类端点。 示例中是否还有其他具有其他端点的控制器? 不是,没有! Stormpath提供了开箱即用的oauth(和许多其他)端点。 一探究竟:

➥ http -v --form POST http://localhost:8080/oauth/token  \
> 'Origin:http://localhost:8080' \
> grant_type=password username=micah+demo.jsmith@stormpath.com password=
POST /oauth/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: localhost:8080
Origin: http://localhost:8080
User-Agent: HTTPie/0.9.2grant_type=password&username=micah%2Bdemo.jsmith%40stormpath.com&password=HTTP/1.1 200 OK
Cache-Control: no-store
Content-Length: 325
Content-Type: application/json;charset=UTF-8
Date: Tue, 04 Aug 2015 16:02:08 GMT
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: account=eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxNDQyNmQxMy1mNThiLTRhNDEtYmVkZS0wYjM0M2ZjZDFhYzAiLCJpYXQiOjE0Mzg3MDQxMjgsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNW9NNFdJM1A0eEl3cDRXaURiUmo4MCIsImV4cCI6MTQzODk2MzMyOH0.wcXrS5yGtUoewAKqoqL5JhIQ109s1FMNopL_50HR_t4; Expires=Wed, 05-Aug-2015 16:02:08 GMT; Path=/; HttpOnly{"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxNDQyNmQxMy1mNThiLTRhNDEtYmVkZS0wYjM0M2ZjZDFhYzAiLCJpYXQiOjE0Mzg3MDQxMjgsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNW9NNFdJM1A0eEl3cDRXaURiUmo4MCIsImV4cCI6MTQzODk2MzMyOH0.wcXrS5yGtUoewAKqoqL5JhIQ109s1FMNopL_50HR_t4","expires_in": 259200,"token_type": "Bearer"
}

这里有很多事情,所以让我们分解一下。

在第一行中,我告诉httpie我想创建一个表单url编码的POST,这就是--formPOST参数的作用。 我正在本地运行的服务器的/oauth/token端点上。 我指定一个Origin标头。 出于我们先前提到的安全原因,与Stormpath进行交互是必需的。 根据OAuth2规范,我要传递grant_type=password以及usernamepassword

响应具有Set-Cookie标头以及包含OAuth2访问令牌的JSON正文。 你猜怎么着? 该访问令牌也是JWT。 以下是已解码的声明:

{"jti": "14426d13-f58b-4a41-bede-0b343fcd1ac0","iat": 1438704128,"sub": "https://api.stormpath.com/v1/accounts/5oM4WI3P4xIwp4WiDbRj80","exp": 1438963328
}

注意sub键。 这就是我验证为的帐户的完整Stormpath URL。 现在,让我们再次点击基本的Hello World端点,仅这次,我们将使用OAuth2访问令牌:

➥ http -v localhost:8080 \
> 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxNDQyNmQxMy1mNThiLTRhNDEtYmVkZS0wYjM0M2ZjZDFhYzAiLCJpYXQiOjE0Mzg3MDQxMjgsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNW9NNFdJM1A0eEl3cDRXaURiUmo4MCIsImV4cCI6MTQzODk2MzMyOH0.wcXrS5yGtUoewAKqoqL5JhIQ109s1FMNopL_50HR_t4'
GET / HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxNDQyNmQxMy1mNThiLTRhNDEtYmVkZS0wYjM0M2ZjZDFhYzAiLCJpYXQiOjE0Mzg3MDQxMjgsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNW9NNFdJM1A0eEl3cDRXaURiUmo4MCIsImV4cCI6MTQzODk2MzMyOH0.wcXrS5yGtUoewAKqoqL5JhIQ109s1FMNopL_50HR_t4
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/0.9.2HTTP/1.1 200 OK
Content-Length: 11
Content-Type: text/plain;charset=UTF-8
Date: Tue, 04 Aug 2015 16:44:28 GMT
Server: Apache-Coyote/1.1Hello John!

请注意,在输出的最后一行中,消息是通过名称寻址我们的。 现在,我们已经使用OAuth2与Stormpath建立了经过身份验证的会话,控制器中的以下几行将检索名字:

Account account = AccountResolver.INSTANCE.getAccount(request);
if (account != null) {name = account.getGivenName();
}

摘要:Java应用程序的令牌认证

在本文中,我们研究了使用JWT进行令牌身份验证如何不仅解决传统方法的问题,而且还为我们提供了可检查的元数据和强大的密码签名的好处。

我们概述了OAuth2协议,并详细介绍了Stormpath的OAuth2实现如何使用JWT。

以下是指向基于令牌的身份验证,JWT和Spring Boot的文章的其他链接:

  • Angular.js的基于令牌的身份验证
  • JJWT –适用于Java和Android的JSON Web令牌
  • Spring Boot Webapp示例快速入门
  • JWT规范

建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

翻译自: https://www.javacodegeeks.com/2016/07/token-authentication-java-applications.html

Java应用程序的令牌认证相关推荐

  1. 认证令牌_Java应用程序的令牌认证

    认证令牌 建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现. 注册 ,再也不会建立auth ...

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

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

  3. 认证令牌_Java应用程序的简单令牌认证

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

  4. Java程序员的认证Sun Certified JAVA Programmer(SCJP)

    Java程序员的认证Sun Certified JAVA Programmer(SCJP) 课程:SL-275 JAVA语言编程 本课程使学员掌握如何使用标准JAVA Development Kit, ...

  5. Java程序员的认证--SUN认证

    文章目录 作用 考试项目 导语:SUN认证是给网络设计界建立的一套认证标准,Sun公司推出了Java以及Solaris技术认证方案. 作用 对于企业而言,可以借助这项认证作为招聘人才的评判标准,或是作 ...

  6. 参加Sun认证Java程序员_sun认证java程序员笔试经验

    sun认证java程序员笔试经验 SCJP测验Java程序设计概念及能力,内容偏重于Java语法及JDK的内容;SCJD则进一步测试用Java开发应用程序的能力,考试者必须先完成一个程序的设计方案,再 ...

  7. 使用Spring Security,Thymeleaf和Okta保护Java应用程序的安全

    永不再构建身份验证 –喜欢构建用户管理? 使用Okta,您可以在几分钟内为您的应用程序添加社交登录,多因素身份验证和OpenID Connect支持. 立即创建一个免费的开发者帐户. 在构建Java应 ...

  8. java 用程序代码解释继承_关于初级java程序员笔试题

    关于初级java程序员笔试题 Sun 认证Java程序员考试内容涉及Java所有相关知识.编程概念及applet开发技巧.下面是小编整理的关于初级java程序员笔试题,欢迎大家参考! 第一题:判断题 ...

  9. .NET Core + JWT令牌认证 + Vue.js 通用动态权限(RBAC)管理系统框架[DncZeus]开源啦!!!...

    DncZeus 前言 关于 DncZeus DncZeus = Dnc + Zeus "Dnc"--.Net Core 的缩写: "Zeus"--中文译为宙斯, ...

最新文章

  1. saltstack二次开发构建自己的api
  2. 工具-Xmind常用快捷键/使用
  3. RedHat YUM configure
  4. 虚函数和纯虚函数的区别是什么?
  5. 小程序居然可以用WXS模拟实现过滤器!
  6. 第二节:ES6新增了let关键字,干嘛用的?
  7. java mongodb 语句,MongoDB语句
  8. 【codevs1052】地鼠游戏
  9. android自定义ClockView
  10. 新浪云sae 部署 thinkphp5
  11. Android性能优化-过度绘制解决方案
  12. 在r中弄方差分析表_使用R语言进行单因素方差分析
  13. ie不能加载flash html,IE浏览器无法显示Flash怎么解决?解决的方法介绍
  14. Chrome 插件收集
  15. 小程序源码:收款码三合一制作-多玩法安装简单
  16. springboot中@SpringBootApplication的扫描范围,以及多模块的扫描问题
  17. (转)怎样更好地理解并记忆泰勒展开式?
  18. TSL协议及抓包分析
  19. 游戏角色3d建模用什么软件
  20. 顾连康复中心一个月费用?医保能报销吗

热门文章

  1. java提高篇之抽象类与接口
  2. Spring MVC常用注解,你会几个?
  3. 【最全最详细】publiccms实现将公共部分提取成单独模块引入
  4. 属性编辑器未在PropertyEditorManager中注册?
  5. Hibernate中使用Criteria查询及注解——(DeptTest.java)
  6. oracle8修改最大连接数,ORACLE查看并修改最大连接数的具体步骤
  7. resnet50加入fpn_FPN+SSD同时兼顾速度和精度的检测器(二)
  8. 如何不用 List.clear() 方法 就清空 list 中的 所有元素(中兴面试)
  9. java记录类型_Java中的记录类型
  10. jax-rs jax-ws_极端懒惰:使用Spring Boot开发JAX-RS服务