1. 実装のアイデアインターフェース署名の目的は、リクエストパラメータが改ざんされていないか、リクエストされたデータがタイムアウトしていないか、データが繰り返し送信されていないかなどを確認することです。 インターフェース署名図 クライアントがリクエストを送信すると、合意された署名方法に従って次のパラメータに署名し、パラメータと署名を一緒にサーバーに送信します。 1. リクエストヘッダー部分(ヘッダー) 2. データ部分 サイン サーバーはハンドオーバー要求を送信した後、受信した「要求ヘッダー部分」と「データ部分」のパラメータも結合します。クライアントが送信した署名が正しいかどうかが検証されます。 2. コードの実装クライアント (Vue) は、まず RSA 暗号化、復号化、署名、検証機能を実装するために「jsrsasign」ライブラリをインストールする必要があります。 npm インストール jsrsasign -save インストールが完了したら、sign.jsをパッケージ化します。 'jsrsasign' から {KJUR、KEYUTIL、hex2b64、b64tohex} をインポートします。 // 署名アルゴリズム const ALGORITHM = 'SHA256withRSA' // 秘密鍵署名 const RSA_SIGN = (privateKey, src) => { const 署名 = 新しい KJUR.crypto.Signature({'alg': ALGORITHM}) // キーを解析するには const priKey = KEYUTIL.getKey(privateKey) 署名.init(priKey) // 署名するプレーンテキストを渡す signature.updateString(src) 定数 a = 署名.sign() // base64 に変換して返す return hex2b64(a) } // 公開鍵検証 const RSA_VERIFY_SIGN = (publicKey, src, data) => { const signature = 新しい KJUR.crypto.Signature({'alg': ALGORITHM, 'prvkeypem': publicKey}) 署名.updateString(ソース) 署名を返す。検証(b64tohex(データ)) } 輸出 { RSA_SIGN、 RSA_VERIFY_SIGN } クライアント (Vue) は sign.js を使用して署名し、署名を検証します。 const src = '私はテスト文字列2です' const publicKey = '-----公開鍵の開始-----\n' + 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC35wxzdTzseajkYL06hEKBCEJu\n' + 'JQ/nySId2oTnsxbLiSTEjpAESSbML1lqkKaIwjrSFZzyLMH6DirsoEQcATqqoCDU\n' + '/H9QNVb5jMSAxxdQusQkTWz6k07bEuy1ppVjpGxNi8o2OGNd+lwPC/hOSDR7lpfm\n' + 'aXLIjEwKSXzil7YAHQIDAQAB\n' + '-----公開鍵終了-----' const privateKey = '-----秘密鍵の開始-----\n' + 'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALfnDHN1POx5qORg\n' + 'vTqEQoEIQm4lD+fJIh3ahOezFsuJJMSOkARJJswvWWqQpojCOtIVnPIswfoOKuyg\n' + 'RBwBOqqgINT8f1A1VvmMxIDHF1C6xCRNbPqTTtsS7LWmlWOkbE2LyjY4Y136XA8L\n' + '+E5INHuWl+ZpcsiMTApJfOKXtgAdAgMBAAECgYB2PAcGSC7mPoW2ZvfiIlx7hurm\n' + '0885D1hu5yohqUOTklXgRWQUTU+zYRHU8LERJgcZQKoKDXqdIPS584Q2mRe0uZMr\n' + 'vaiaBVEnHQreUJUQ8UN12pPUdBHDZvOk3L7/fZHk6A8uy5e09p2rsn+Vfki3zijp\n' + '7Pd758HMtjuiHBb2QQJBAOuN6jdWBr/zb7KwM9N/cD1jJd6snOTNsLazH/Z3Yt0T\n' + 'jlsFmRJ6rIt/+jaLKG6YTR8SFyW5LIQTbreeQHPw4FECQQDH3Wpd/mBMMcgpxLZ0\n' + 'F5p1ieza+VA5fbxkQ0hdubEP26B6YwhkTB/xMSOwEjmUI57kfgOTvub36/peb8rI\n' + 'JdwNAkB3fzwlrGeqMzYkIU15avomuki46TqCvHJ8jOyXHUOzQbuDI5jfDgrAjkEC\n' + 'MKBnUq41J/lEMueJbU5KqmaqKrWxAkAyexlHnl1iQVymOBpBXkjUET8y26/IpZp0\n' + '1I2tpp4zPCzfXK4c7yFOQTQbX68NXKXgXne21Ivv6Ll3KtNUFEPtAkBcx5iWU430\n' + '0/s6218/enaa8jgdqw8Iyirnt07uKabQXqNnvbPYCgpeswEcSvQqMVZVKOaMrjKO\n' + 'G319Es83iq/m\n' + '-----秘密鍵終了-----\n' console.log('プレーンテキスト:', src) 定数データ = RSA_SIGN(秘密鍵、src) console.log('署名された結果:', データ) const res = RSA_VERIFY_SIGN(公開鍵、ソース、データ) console.log('署名検証結果:', res) サーバー (Spring Boot) はリクエストを受信した後、データと署名を検証する必要があります。 まず、依存関係である hutool ツールキットを導入します。Hutool は Java ツールキットであり、単なるツールキットです。コードの各行を簡素化し、すべてのメソッドを削減し、Java 言語を「使いやすく」するのに役立ちます。 公式サイト: https://www.hutool.cn/ pom.xml の下に次の構成を追加します。 <依存関係> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <バージョン>5.3.5</バージョン> </依存関係> サーバー (Spring boot) は、まずクライアント (Vue) から要求されたデータを取得する必要があります。前述のように、リクエスト データには「リクエスト ヘッダー部分」と「データ部分」の 2 つの部分があります。したがって、上記 2 つの部分を取得するにはインターセプターを構成する必要があります。 インターセプター (MyInterceptor.java) を構成します。コードは次のようになります。 lombok.extern.slf4j.Slf4j をインポートします。 org.springframework.beans.factory.annotation.Value をインポートします。 org.springframework.stereotype.Component をインポートします。 org.springframework.util.StreamUtils をインポートします。 org.springframework.web.servlet.HandlerInterceptor をインポートします。 javax.servlet.http.HttpServletRequest をインポートします。 javax.servlet.http.HttpServletResponse をインポートします。 翻訳者 @成分 パブリッククラス MyInterceptor は HandlerInterceptor を実装します { @オーバーライド public boolean preHandle(HttpServletRequest リクエスト、HttpServletResponse レスポンス、オブジェクト ハンドラ) 例外をスローします { //リクエストパラメータを取得する String queryString = request.getQueryString(); log.info("リクエストパラメータ:{}", queryString); // ヘッダーを取得する log.info("キー:{}",request.getHeader("タイムスタンプ")); MyHttpServletRequestWrapper は、リクエストをラッパーに追加します。 //リクエスト本文を取得する byte[] bodyBytes = StreamUtils.copyToByteArray(myRequestWrapper.getInputStream()); 文字列本体 = 新しい文字列(bodyBytes、request.getCharacterEncoding()); log.info("リクエスト本文: {}", body); true を返します。 } } 「リクエスト ボディ」を取得する場合、「HttpServletRequest」は 1 回しか読み取れないため、インターセプターが読み取った後、後続のコントローラーは読み取り時に空になります。そのため、HttpServletRequestWrapper を書き換える必要があります。 org.springframework.util.StreamUtils をインポートします。 javax.servlet.ReadListener をインポートします。 javax.servlet.ServletInputStream をインポートします。 javax.servlet.http.HttpServletRequest をインポートします。 javax.servlet.http.HttpServletRequestWrapper をインポートします。 java.io.* をインポートします。 パブリッククラス MyHttpServletRequestWrapper は HttpServletRequestWrapper を拡張します { /** * キャッシュされたHTTPボディ */ プライベートbyte[]本体; パブリック MyHttpServletRequestWrapper(HttpServletRequest リクエスト) は IOException をスローします { super(リクエスト); 本文 = StreamUtils.copyToByteArray(request.getInputStream()); } @オーバーライド パブリックServletInputStream getInputStream()はIOExceptionをスローします{ 入力ストリーム bodyStream = 新しい ByteArrayInputStream(body); 新しいServletInputStream()を返す{ @オーバーライド パブリックint read() はIOExceptionをスローします { bodyStream.read() を返します。 } @オーバーライド パブリックブール値isFinished() { false を返します。 } @オーバーライド パブリックブール値isReady() { true を返します。 } @オーバーライド パブリック void setReadListener(ReadListener readListener) { } }; } @オーバーライド パブリック BufferedReader getReader() は IOException をスローします { 新しい BufferedReader(新しい InputStreamReader(getInputStream())) を返します。 } } その後、フィルターを作成し、「ServletRequest」を「MyHttpServletRequestWrapper」に置き換える必要があります。コードは次のとおりです。 lombok.extern.slf4j.Slf4j をインポートします。 javax.servlet.* をインポートします。 javax.servlet.http.HttpServletRequest をインポートします。 java.io.IOException をインポートします。 翻訳者 パブリッククラスRepeatedlyReadFilterはFilterを実装します{ @オーバーライド パブリック void init(FilterConfig filterConfig) は ServletException をスローします { } @オーバーライド パブリック void doFilter(ServletRequest servletRequest、ServletResponse servletResponse、FilterChain filterChain) は IOException、ServletException をスローします { ServletRequest リクエストラッパー = null; if (servletRequest インスタンス HttpServletRequest) { リクエストラッパー = 新しい MyHttpServletRequestWrapper((HttpServletRequest) servletRequest); } リクエストラッパーが null の場合 フィルターチェーン.doFilter(サーブレットリクエスト、サーブレットレスポンス); } それ以外 { filterChain.doFilter(リクエストラッパー、サーブレットレスポンス); } } @オーバーライド パブリックvoidの破棄(){ } } 次に、カスタム構成 CorsConfig.java を作成し、構成にフィルターとインターセプターを追加します。 com.xyf.interceptor.MyInterceptor をインポートします。 com.xyf.interceptor.RepeatedlyReadFilter をインポートします。 org.springframework.beans.factory.annotation.Autowired をインポートします。 org.springframework.boot.web.servlet.FilterRegistrationBean をインポートします。 org.springframework.context.annotation.Bean をインポートします。 org.springframework.context.annotation.Configuration をインポートします。 org.springframework.web.servlet.config.annotation.InterceptorRegistry をインポートします。 org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport をインポートします。 @構成 パブリッククラスCorsConfigはWebMvcConfigurationSupportを拡張します{ プライベート MyInterceptor myInterceptor; オートワイヤード パブリック CorsConfig (MyInterceptor myInterceptor) { this.myInterceptor = myInterceptor; } //フィルターを登録@Bean パブリック FilterRegistrationBean<繰り返し読み取りフィルタ> 繰り返し読み取りフィルタ() { FilterRegistrationBean 登録 = 新しい FilterRegistrationBean(); 繰り返し読み取りフィルターを繰り返し読み取りフィルター = 新しい繰り返し読み取りフィルター(); 登録.setFilter(繰り返し読み取りフィルタ) 登録.addUrlPatterns("/*"); 返品登録; } @オーバーライド 保護された void addInterceptors(InterceptorRegistry レジストリ) { // addPathPatterns はインターセプトする必要がある名前空間を追加します。 // excludePathPatterns は除外インターセプト名前空間を追加します registry.addInterceptor(myInterceptor).addPathPatterns("/**"); //.excludePathPatterns("/api/sys/login") } } 最後に、署名の検証を完了します。コードは次のとおりです。 cn.hutool.core.codec.Base64 をインポートします。 cn.hutool.crypto.SecureUtil をインポートします。 cn.hutool.crypto.asymmetric.Sign をインポートします。 cn.hutool.crypto.asymmetric.SignAlgorithm をインポートします。 byte[] data = "私はテスト文字列2です".getBytes(); 文字列公開キー = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC35wxzdTzseajkYL06hEKBCEJu\n" + 「JQ/nySId2oTnsxbLiSTEjpAESSbML1lqkKaIwjrSFZzyLMH6DirsoEQcATqqoCDU\n」+ "/H9QNVb5jMSAxxdQusQkTWz6k07bEuy1ppVjpGxNi8o2OGNd+lwPC/hOSDR7lpfm\n" + 「aXLIjEwKSXzil7YAHQIDAQAB」; 署名 sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA,null,publicKey); //クライアントから送信された署名文字列 qm = "IhY3LNuFn0isud1Pk6BL2eJV3Jl/UzDCYsdG9CYyJwOGqwnzStsv/RiYLnVP4bnQh1NRPMazY6ux/5Zz5Ypcx6RI5W1p5BDbO2afuIZX7x/eIu5utwsanhbxEfvm3XOsyuTbnMDh6BQUrXb4gUz9qgt9IXWjQdqnQRRv3ywzWcA="; byte[] signed = Base64.decode(qm); //署名を検証する boolean verify = sign.verify(data, signed); 3. 公開鍵と秘密鍵の生成いくつかのウェブサイトを通じてオンラインで公開鍵と秘密鍵を生成できます: https://www.bejson.com/enc/rsa/ bejson はオンラインで公開鍵と秘密鍵を生成します 4. その他の問題クライアントが署名を追加し、サーバーが署名を検証するためです。したがって、署名の追加と検証の方法は一貫している必要があり、そうでないと署名を検証できません。 Vue と Java では署名ツール ライブラリが異なるため、使用する前に必ずテストしてください。 これで、Vue+Springboot のインターフェースシグネチャを実装するサンプルコードに関するこの記事は終了です。Springboot インターフェースシグネチャの関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Hadoop を使用せずに Linux 環境に Spark のスタンドアロン バージョンをインストールする方法
>>: MySQL 5.7 と Mac 上の MySql の詳細なインストール図をダウンロードする
この記事では、主にMACオペレーティングシステムでのMySQL5.7とMySQLWorkbenchの...
まず、nginx コンテナ内の構造:コンテナを入力します: docker exec -it b511...
目次1. データベース操作1.1 データベースの表示1.2 データベースを作成する1.3 データベー...
目次ルーティングプラグインをモジュール方式で使用するルートの使用宣言型ナビゲーションプログラムによる...
読み取り専用入力を実現するには、無効と読み取り専用の 2 つの方法があります。当然、どちらの結果も読...
この記事では、LinuxにバイナリモードでMySQLをインストールする具体的な手順を参考までに紹介し...
1. MySQL インストール パッケージをダウンロードします(ここにはコツがあります。おそらく、こ...
この記事では、例を使用して MySQL カーソルの概念と使用方法を説明します。ご参考までに、詳細は以...
Unicode 署名 BOM - BOM とは何ですか? BOM は Byte Order Mark...
MySQL 8.0: InnoDB のラージ オブジェクトに対する MVCCこの記事では、MySQL...
HTML はタグと属性で構成されており、これらを組み合わせてブラウザにページの表示方法を指示します。...
この記事では、MySQL ユーザー管理操作について説明します。ご参考までに、詳細は以下の通りです。こ...
目次1. 概要1.1 querySelector() と querySelectorAll() の使...
目次1. テンプレート文字列とは何ですか? 2. 複数行のテンプレート文字列2.1 式付きテンプレー...
通常、vue プロジェクトではルーティングを使用します。vue-router は vue.js の公...