1. UmsetzungsideenDer Zweck der Schnittstellensignatur besteht darin, sicherzustellen, dass die Anforderungsparameter nicht manipuliert werden, dass keine Zeitüberschreitung bei den angeforderten Daten vorliegt, dass die Daten wiederholt übermittelt werden usw. Schnittstellensignaturdiagramm Wenn der Client eine Anforderung sendet, signiert er die folgenden Parameter gemäß der vereinbarten Signaturmethode und sendet dann die Parameter und die Signatur zusammen an den Server: 1. Header-Teil anfordern (Header) 2. Datenteil Zeichen Nachdem der Server die Übergabeanforderung übermittelt hat, fügt er auch die empfangenen Parameter „Anforderungsheaderteil“ und „Datenteil“ zusammen. Anschließend wird die Richtigkeit der vom Kunden übermittelten Unterschrift überprüft. 2. Code-Implementierung Der Client (Vue) muss zuerst die Bibliothek „jsrsasign“ installieren, um RSA-Verschlüsselungs-, Entschlüsselungs-, Signierungs- und Verifizierungsfunktionen zu implementieren. npm installiere jsrsasign -save Nach Abschluss der Installation verpacken Sie sign.js importiere {KJUR, KEYUTIL, hex2b64, b64tohex} aus 'jsrsasign' // Signaturalgorithmus const ALGORITHM = 'SHA256withRSA' // Signatur des privaten Schlüssels const RSA_SIGN = (privateKey, src) => { const signature = new KJUR.crypto.Signature({'alg': ALGORITHM}) // Um den Schlüssel zu analysieren const priKey = KEYUTIL.getKey(privateKey) signature.init(priKey) // Übergeben Sie den zu signierenden Klartext signature.updateString(src) const a = Signatur.sign() // In Base64 konvertieren und zurückgeben return hex2b64(a) } // Überprüfung des öffentlichen Schlüssels const RSA_VERIFY_SIGN = (publicKey, src, data) => { const signature = new KJUR.crypto.Signature({'alg': ALGORITHM, 'prvkeypem': publicKey}) Signatur.updateString(src) Signatur zurückgeben.überprüfen(b64tohex(Daten)) } exportieren { RSA_SIGN, RSA_VERIFY_SIGN } Der Client (Vue) verwendet sign.js, um die Signatur zu signieren und zu überprüfen. const src = 'Ich bin eine Testzeichenfolge 2' const publicKey = '-----BEGIN PUBLIC KEY-----\n' + 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC35wxzdTzseajkYL06hEKBCEJu\n' + 'JQ/nySId2oTnsxbLiSTEjpAESSbML1lqkKaIwjrSFZzyLMH6DirsoEQcATqqoCDU\n' + '/H9QNVb5jMSAxxdQusQkTWz6k07bEuy1ppVjpGxNi8o2OGNd+lwPC/hOSDR7lpfm\n' + 'aXLIjEwKSXzil7YAHQIDAQAB\n' + '-----ENDE DES ÖFFENTLICHEN SCHLÜSSELS-----' const privateKey = '-----BEGIN PRIVATE KEY-----\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' + '-----ENDE DES PRIVATEN SCHLÜSSELS-----\n' console.log('Klartext:', src) const data = RSA_SIGN(privaterSchlüssel, src) console.log('Signiertes Ergebnis:', Daten) const res = RSA_VERIFY_SIGN(öffentlicher Schlüssel, Quelle, Daten) console.log('Ergebnis der Signaturüberprüfung:', res) Nachdem der Server (Spring Boot) die Anfrage erhalten hat, muss er die Daten und die Signatur überprüfen. Stellen Sie zunächst die Abhängigkeit vor – das Hutool-Toolkit. Hutool ist ein Java-Toolkit und es ist nur ein Toolkit. Es hilft uns, jede Codezeile zu vereinfachen, jede Methode zu reduzieren und die Java-Sprache „süß“ zu machen. Offizielle Website: https://www.hutool.cn/ Fügen Sie die folgende Konfiguration unter pom.xml hinzu: <Abhängigkeit> <groupId>cn.hutool</groupId> <artifactId>hutool-alles</artifactId> <version>5.3.5</version> </Abhängigkeit> Der Server (Spring Boot) muss zuerst die vom Client (Vue) angeforderten Daten abrufen. Wie oben beschrieben, bestehen die Anforderungsdaten aus zwei Teilen, nämlich dem „Anforderungsheaderteil“ und dem „Datenteil“. Daher ist es notwendig, den Interceptor zu konfigurieren, um die beiden oben genannten Teile zu erhalten. Konfigurieren Sie den Interceptor (MyInterceptor.java). Der Code lautet wie folgt: importiere lombok.extern.slf4j.Slf4j; importiere org.springframework.beans.factory.annotation.Value; importiere org.springframework.stereotype.Component; importiere org.springframework.util.StreamUtils; importiere org.springframework.web.servlet.HandlerInterceptor; importiere javax.servlet.http.HttpServletRequest; importiere javax.servlet.http.HttpServletResponse; @Slf4j @Komponente öffentliche Klasse MyInterceptor implementiert HandlerInterceptor { @Überschreiben public boolean preHandle(HttpServletRequest-Anforderung, HttpServletResponse-Antwort, Objekthandler) löst Exception aus { //Anforderungsparameter abrufen String queryString = request.getQueryString(); log.info("Anforderungsparameter:{}", queryString); // Den Header abrufen log.info("Schlüssel:{}",request.getHeader("Zeitstempel")); MyHttpServletRequestWrapper myRequestWrapper = neuer MyHttpServletRequestWrapper(Anfrage); // Den Anforderungstext abrufen byte[] bodyBytes = StreamUtils.copyToByteArray(myRequestWrapper.getInputStream()); String-Body = neuer String (bodyBytes, request.getCharacterEncoding()); log.info("Anforderungstext: {}", body); gibt true zurück; } } Da „HttpServletRequest“ beim Abrufen des „Anforderungstexts“ nur einmal gelesen werden kann, ist der nachfolgende Controller nach dem Lesen durch den Interceptor beim Lesen leer. Daher müssen Sie den HttpServletRequestWrapper neu schreiben: importiere org.springframework.util.StreamUtils; importiere javax.servlet.ReadListener; importiere javax.servlet.ServletInputStream; importiere javax.servlet.http.HttpServletRequest; importiere javax.servlet.http.HttpServletRequestWrapper; importiere java.io.*; öffentliche Klasse MyHttpServletRequestWrapper erweitert HttpServletRequestWrapper { /** * Der zwischengespeicherte HTTP-Text */ privater Byte[]-Text; öffentliche MyHttpServletRequestWrapper(HttpServletRequest Anfrage) wirft IOException { super(Anfrage); body = StreamUtils.copyToByteArray(request.getInputStream()); } @Überschreiben öffentlicher ServletInputStream getInputStream() wirft IOException { InputStream bodyStream = neuer ByteArrayInputStream(body); gibt neuen ServletInputStream() zurück { @Überschreiben öffentliche int read() wirft IOException { gibt bodyStream.read() zurück; } @Überschreiben public boolean istFertig() { gibt false zurück; } @Überschreiben öffentlicher Boolescher Wert istBereit() { gibt true zurück; } @Überschreiben öffentliche Leere setReadListener (ReadListener readListener) { } }; } @Überschreiben öffentlicher BufferedReader getReader() wirft IOException { gibt einen neuen BufferedReader zurück (neuer InputStreamReader (getInputStream())); } } Anschließend müssen Sie einen Filter erstellen und "ServletRequest" durch "MyHttpServletRequestWrapper" ersetzen. Der Code lautet wie folgt: importiere lombok.extern.slf4j.Slf4j; importiere javax.servlet.*; importiere javax.servlet.http.HttpServletRequest; importiere java.io.IOException; @Slf4j öffentliche Klasse RepeatedlyReadFilter implementiert Filter { @Überschreiben public void init(FilterConfig filterConfig) throws ServletException { } @Überschreiben public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { ServletRequest requestWrapper = null; if (servletRequest-Instanz von HttpServletRequest) { requestWrapper = neuer MyHttpServletRequestWrapper((HttpServletRequest) servletRequest); } wenn(requestWrapper == null) { filterChain.doFilter(servletAnfrage, servletAntwort); } anders { filterChain.doFilter(requestWrapper, servletResponse); } } @Überschreiben öffentliche Leere zerstören() { } } Erstellen Sie dann eine benutzerdefinierte Konfiguration, CorsConfig.java, und fügen Sie der Konfiguration Filter und Interceptors hinzu: importiere com.xyf.interceptor.MyInterceptor; importiere com.xyf.interceptor.RepeatedlyReadFilter; importiere org.springframework.beans.factory.annotation.Autowired; importiere org.springframework.boot.web.servlet.FilterRegistrationBean; importiere org.springframework.context.annotation.Bean; importiere org.springframework.context.annotation.Configuration; importiere org.springframework.web.servlet.config.annotation.InterceptorRegistry; importiere org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; @Konfiguration öffentliche Klasse CorsConfig erweitert WebMvcConfigurationSupport { privater MyInterceptor meinInterceptor; @Autowired öffentliche CorsConfig (MyInterceptor myInterceptor) { dies.meinInterceptor = meinInterceptor; } //Filter registrieren@Bean öffentliche FilterRegistrationBean<RepeatedlyReadFilter> wiederholtReadFilter() { FilterRegistrationBean-Registrierung = neue FilterRegistrationBean(); WiederholtesLesenFilter wiederholtLesenFilter = neuer wiederholtesLesenFilter(); Registrierung.setFilter(wiederholtReadFilter); Registrierung.addUrlPatterns("/*"); Rückmeldewesen; } @Überschreiben geschützt void addInterceptors(InterceptorRegistry registry) { // addPathPatterns fügt den Namespace hinzu, der abgefangen werden muss; // excludePathPatterns fügt den Namespace für die Ausschluss-Interception hinzu registry.addInterceptor(myInterceptor).addPathPatterns("/**"); //.excludePathPatterns("/api/sys/login") } } Schließen Sie abschließend die Signaturprüfung ab. Der Code lautet wie folgt: importiere cn.hutool.core.codec.Base64; importiere cn.hutool.crypto.SecureUtil; importiere cn.hutool.crypto.asymmetric.Sign; importiere cn.hutool.crypto.asymmetric.SignAlgorithm; byte[] data = "Ich bin eine Testzeichenfolge 2".getBytes(); Zeichenfolge öffentlicher Schlüssel = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC35wxzdTzseajkYL06hEKBCEJu\n" + "JQ/nySId2oTnsxbLiSTEjpAESSbML1lqkKaIwjrSFZzyLMH6DirsoEQcATqqoCDU\n" + "/H9QNVb5jMSAxxdQusQkTWz6k07bEuy1ppVjpGxNi8o2OGNd+lwPC/hOSDR7lpfm\n" + „aXLIjEwKSXzil7YAHQIDAQAB“; Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA,null,publicKey); //Vom Client gesendete Signaturzeichenfolge qm = "IhY3LNuFn0isud1Pk6BL2eJV3Jl/UzDCYsdG9CYyJwOGqwnzStsv/RiYLnVP4bnQh1NRPMazY6ux/5Zz5Ypcx6RI5W1p5BDbO2afuIZX7x/eIu5utwsanhbxEfvm3XOsyuTbnMDh6BQUrXb4gUz9qgt9IXWjQdqnQRRv3ywzWcA="; byte[] signiert = Base64.decode(qm); //Überprüfen Sie die Signatur boolean verify = sign.verify(data, signed); 3. Generierung öffentlicher und privater SchlüsselSie können öffentliche und private Schlüssel online auf einigen Websites generieren: https://www.bejson.com/enc/rsa/ bejson generiert öffentliche und private Schlüssel online 4. Andere ProblemeWeil der Client die Signatur hinzufügt und der Server die Signatur überprüft. Daher muss die Methode zum Hinzufügen und Überprüfen von Signaturen konsistent sein, da die Signatur sonst nicht überprüft werden kann. Vue und Java verfügen über unterschiedliche Signatur-Toolbibliotheken. Testen Sie diese daher unbedingt vor der Verwendung. Dies ist das Ende dieses Artikels über den Beispielcode von Vue+Springboot zur Implementierung der Schnittstellensignatur. Weitere verwandte Inhalte zur Springboot-Schnittstellensignatur finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen! Das könnte Sie auch interessieren:
|
Der Standardtyp varchar in MySQL ist case-insensi...
Bei Ubuntu 20.04 ist die Root-Anmeldung standardm...
Panther begann als Anfänger und ich bin immer noc...
Es ist sehr praktisch, den virtuellen Host vhost ...
Kerncode /*-------------------------------- Suche...
Inhaltsverzeichnis Vorwort Was sind asynchrone It...
Hinweis: Die derzeit beliebtesten Front-End-Frame...
Vorwort Das Sortieren ist eine grundlegende Funkt...
Ich habe schon lange keinen Blog mehr geschrieben...
Wir haben viele Server, die häufig von externen N...
In diesem Artikel wird der spezifische Code von j...
Vorwort Das einfache Verständnis von MySQL-Berech...
Als ich kürzlich mit C# ein Webprogramm erstellte,...
Inhaltsverzeichnis 1. Vorbereitung 2. Dekompressi...
1. Installation Tipp: Derzeit gibt es kein offizi...