挨拶良い人。apacheでユーザー名トークンを暗号化するcxf
私は消費したいソープWebサービスを持っています。実際のプロジェクト、特にユーザー名トークンの暗号化に必要なものをシミュレートする小さなプロジェクトを作成しました。
以下に示すように、クライアント側でパスワードを暗号化する方法の提供のステップがあります。
- は暗号化されていないパスワード値を書き込みます。
- 次に、手順1で作成したデータのブロックを、パスワードキー証明書の公開部分で暗号化します。 RSAアルゴリズムを使用し、PKCS#1.5のパディング(OAEPではなく)を使用し、結果を暗号化されたストリームに追加します。これはAPIを介して送信される暗号化されたパスワードになります。
- 結果の暗号化バイト配列を、base64エンコーディングを使用して文字列に変換します。イニシエータのSecurityCredential値としてAPIリクエストにこのbase64でエンコードされた文字列を表示します。
- この目的のためにイニシエータに発行されたX509証明書から公開鍵で暗号化されるパスワード。
これまでのところ、私はクライアントとサーバーを作成することができ、リクエストを送信して応答を得ることができました。
ClientPasswordCallbackクラスにpasswordというプレーンテキストのユーザー名トークンを渡し、ServerPasswordCallbackクラスのこれらのクレデンシャルをチェックすることで、Webサービスを保護することもできます。
私はさらに行っているとで別々のリクエストがWSS4Jを使用して、メッセージのボディ部を暗号化し、RSA、X509私はclientKey.jksに格納されている公開鍵とのPrivateKeyに保存されている秘密鍵を持っていることにより、 .jksを使用し、クライアントとサーバーのパスワードコールバックハンドラで適切なパスワードを提供することで、クライアントで本体部分を暗号化し、サーバーで復号化することができました。
チャレンジ:上記の2つの手順を1回のリクエストで組み合わせると、パブリックキーを使用してユーザー名トークンのパスワードを暗号化し、そのパスワードをサーバー側は秘密鍵を使用します。
NB私は、jdkに付属のkeygenツールを使用してテスト用のキーを生成しました。
ClientPasswordCallbackクラスには、clientKey.jksキーストア用のパスワードと暗号化が必要なその他のパスワードの2つのパスワードがあると思います。
これは私がこれまでにアーカイブすることができたものです:
クライアント側
TestMathUtilityクラス
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
// Use the URL defined in the soap address portion of the WSDL
factory.setAddress("http://localhost:8080/MathUtility/services/MathUtilityPort");
// Utilize the class which was auto-generated by Apache CXF wsdl2java
factory.setServiceClass(MathUtility.class);
Object client = factory.create();
// Adding Logging Interceptors
LoggingOutInterceptor loggingOutInterceptor = new LoggingOutInterceptor();
loggingOutInterceptor.setPrettyLogging(true);
ClientProxy.getClient(client).getOutInterceptors().add(loggingOutInterceptor);
LoggingInInterceptor loggingInInterceptor = new LoggingInInterceptor();
loggingInInterceptor.setPrettyLogging(true);
ClientProxy.getClient(client).getInInterceptors().add(loggingInInterceptor);
// Set up WS-Security Encryption
// Reference: https://ws.apache.org/wss4j/using.html
Map<String, Object> props = new HashMap<String, Object>();
props.put(WSHandlerConstants.USER, "testkey");
props.put(WSHandlerConstants.ACTION, WSHandlerConstants.ENCRYPT);
props.put(WSHandlerConstants.PASSWORD_TYPE, "PasswordText");
props.put(WSHandlerConstants.ENC_PROP_FILE, "clientKeystore.properties");
props.put(WSHandlerConstants.ENCRYPTION_PARTS, "{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body");
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());
WSS4JOutInterceptor wss4jOut = new WSS4JOutInterceptor(props);
ClientProxy.getClient(client).getOutInterceptors().add(wss4jOut);
try {
// Call the Web Service to perform an operation
int response = ((MathUtility)client).addIntegers(5, 10);
System.out.println("Response we've got ========= "+response);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
ClientPasswordCallbackクラス
public class ClientPasswordCallback implements CallbackHandler {
@Override
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
// set the password for our message.
pc.setPassword("clientstorepass");
}
}
サーバ側
MathUtilityクラス
@WebService(targetNamespace = "http://utility.math.com/", portName = "MathUtilityPort", serviceName = "MathUtilityService")
public class MathUtility {
public int addIntegers(int firstNum, int secondNum) {
return firstNum + secondNum;
}
public int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result = result * i;
}
return result;
}
}
ServerPasswordCallbackクラス
public class ServerPasswordCallback implements CallbackHandler {
@Override
public void handle(Callback[] arg0) throws IOException,
UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) arg0[0];
// set the password for our message.
pc.setPassword("storepass");
}
}
CXF-beans.xmlの
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<bean id="myPasswordCallback" class="com.math.utility.security.ServerPasswordCallback"/>
<jaxws:endpoint xmlns:tns="http://utility.math.com/" id="mathutility"
implementor="com.math.utility.MathUtility" wsdlLocation="wsdl/mathutility.wsdl"
endpointName="tns:MathUtilityPort" serviceName="tns:MathUtilityService"
address="/MathUtilityPort">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
<jaxws:inInterceptors>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="user" value="testkey"/>
<entry key="action" value="Encrypt"/>
<entry key="passwordType" value="PasswordText"/>
<entry key="decryptionParts" value="{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body"/>
<entry key="decryptionPropFile" value="serverKeystore.properties"/>
<entry key="passwordCallbackRef">
<ref bean="myPasswordCallback"/>
</entry>
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
</jaxws:endpoint>
clientKeyStore.propertiesは同じ構造をサーバー側で使用されて提供されていない使用
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.file=clientkeystore.jks
org.apache.ws.security.crypto.merlin.keystore.password=clientstorepass
org.apache.ws.security.crypto.merlin.keystore.type=jks
.jksファイルをファイル
NB私は春を使用していません。カスタムは、あなたのWebサービスにそれをフックする方法verifyCustomPassword(UsernameToken usernameToken, RequestData data) in UsernameTokenValidator
をオーバーライドすることができダイジェスト持つようにしたい場合は
こんにちはフランク、あなたの時間と入力していただきありがとうございます。私は公開鍵を使ってパスワードを暗号化したい。私はクライアントコードでこれを行うことを楽しみにしています: 'props.put(WSHandlerConstants.ENCRYPTION_PARTS、{Content} {http://schemas.xmlsoap.org/soap/envelope/} Body"); ' – chilopoda
しかし、Bodyを暗号化するのではなく、ユーザー名トークンのみを暗号化するようにUsernameTokenに変更する必要があります。それは可能ですか、提案したとおりにプログラムでパスワードを暗号化し、ヘッダーに渡す必要がありますか? – chilopoda
こんにちは、パスワードを平文またはダイジェストとして送信することができます。つまり、一方通しのハッシュを意味します。パスワードを暗号化して解読する必要がある場合は、私の提案する解決策を使用する必要があります。 – Frank