FRINGE Sicherheit Grundlegende Einführung
Ich werde hier nicht zu viel Einführung in die Frühlingssicherheit geben. Weitere Informationen finden Sie in der offiziellen Dokumentation.
Ich werde nur über die Kernfunktionen der Springsicherheit sprechen:
Grundlegende Umweltkonstruktion
Hier verwenden wir Springboot als grundlegender Rahmen des Projekts. Ich verwende die Maven -Methode für das Paketmanagement. Hier geben wir hier zunächst die Methode zur Integration der Frühlingssicherheit an.
<Depelencies> ... <Depopentcy> <gruppe> org.springframework.boot </Groupid> <artifactid> Spring-Boot-Starter-Security </artifactid> </abhängig> ... </abhängig>
Stellen Sie dann eine Web -Layer -Anforderungsschnittstelle fest
@RastController @requestMapping ("/user") public class userController {@getMapping public String getUsers () {return "Hallo Spring Security"; }}Als nächstes können Sie das Projekt direkt ausführen und die Schnittstelle anrufen, um den Effekt anzuzeigen.
Rufen Sie die Webseite an
Wir machen zuerst den Schnittstellenaufruf über den Browser und greifen direkt auf http: // localhost: 8080/user zu. Wenn auf die Schnittstelle normal zugegriffen werden kann, sollte "Hello Spring Security" angezeigt werden.
Wir können jedoch nicht normal darauf zugreifen, und das Authentifizierungs -Eingangsfeld in der folgenden Abbildung wird angezeigt
Dies liegt daran, dass im Springboot die Standard -Frühjahrssicherheit wirksam ist. Zu diesem Zeitpunkt sind die Schnittstellen geschützt und wir müssen die Überprüfung bestehen, um normal auf sie zugreifen zu können. Spring Security bietet einem Standardbenutzer, der Benutzername ist Benutzer und das Kennwort wird automatisch generiert, wenn das Projekt gestartet wird.
Wenn wir das Projekt -Startprotokoll überprüfen, finden wir das folgende Protokoll
Verwenden des Standardsicherheitskennworts: 62CCF9CA-9FBE-4993-8566-8468CC33C28C
Natürlich muss das Passwort, das Sie sehen, anders sein als meine. Wir melden uns direkt mit dem Benutzer und dem Passwort im Startprotokoll an.
Nachdem Sie sich erfolgreich angemeldet haben, springen Sie zu der Seite, auf der die Schnittstelle normal aufgerufen wird.
Wenn Sie von Anfang an keine Spring Security aktivieren möchten, können Sie Folgendes in der Konfigurationsdatei konfigurieren:
# Security Enable Security.basic.Enabled = false
Die Login -Box, die ich gerade gesehen habe, wurde von Spring Security bereitgestellt, die als HTTPBasiclogin bezeichnet wird. Es ist nicht das, was wir von unserem Produkt wollen. Unser Front-End führt im Allgemeinen die Benutzeranmeldungsüberprüfung durch die Formularübermittlung durch. Daher müssen wir unsere eigene Authentifizierungslogik anpassen.
Passen Sie die Benutzerauthentifizierungslogik an
Jedes System muss über einen eigenen Satz von Benutzersystemen verfügen, sodass wir unsere eigene Authentifizierungslogik und Anmeldestellung anpassen müssen.
Hier müssen wir Springsicherheit entsprechend konfigurieren
@ConfigurationPublic Class BrowerSecurityConfig erweitert WebSecurityConFigurerAdapter {@Override Protected void configure (httpecurity http) Ausnahme aus der Ausnahme {http.formlogin () // Definieren Sie die Login -Seite, die übertragen werden muss, wenn der Benutzer log. geschützt werden und nicht geschützt werden müssen. }}Konfigurieren Sie als Nächstes die Benutzerauthentifizierungslogik, da wir über ein eigenes Benutzersystem verfügen.
@ComponentPublic Class MyUSerDetailsService implementiert UserDetailsService {private logger logger = loggerFactory.getLogger (getClass ()); @Override public userDetails loadUserByUserName (String -Benutzername) löst userernamenotFoundException {logger.info ("Benutzername des Benutzers: {}", Benutzername); // Todo gemäß dem Benutzernamen, das entsprechende Kennwort finden und die Benutzerinformationen zusammenfassen und zurückgeben. Parameter sind: Benutzername, Kennwort, Benutzerberechtigungen user user = neuer Benutzer (Benutzerame, "123456", Authorityutils.CommaseParatedStringtoAuthorityList ("Admin")); Benutzer zurückgeben; }} Wir haben hier nicht zu viel Überprüfung durchgeführt. Der Benutzername kann nach Belieben ausgefüllt werden, aber das Passwort muss "123456" sein, damit wir uns erfolgreich anmelden können.
Gleichzeitig können wir sehen, dass der dritte Parameter des Benutzerobjekts hier die Berechtigungen des aktuellen Benutzers darstellt, und wir haben ihn auf "admin" festgelegt.
Führen Sie das Programm aus, um es zu testen, und Sie werden feststellen, dass sich die Anmeldeschnittstelle geändert hat.
Dies liegt daran, dass wir http.formLogin() in der Konfigurationsdatei konfiguriert haben
Füllen wir hier einen Benutzer aus und füllen Sie dann eine falsche (nicht-123456) Version aus. Dies führt zu einem Überprüfungsfehler:
Gleichzeitig wird auch der Benutzer, den Sie beim Anmelden eingemacht haben, auch ausgedruckt.
Versuchen wir nun, sich mit dem richtigen Passwort anzumelden. Sie können feststellen, dass es die Überprüfung übergeben und zur richtigen Schnittstellen -Call -Seite springen.
Benutzerdetails
Als wir gerade MyUserDetailsService geschrieben haben, haben wir eine Methode implementiert und einen UserDetails zurückgegeben. Dieses Benutzerdetails ist ein Objekt, das Benutzerinformationen zusammenfasst, das sieben Methoden enthält
Public Interface UserDetails erweitert serialisierbar {// Incapsulierte Berechtigungsinformationen Sammlung <? erweitert GrantedAuthority> GetAuthorities (); // Kennwortinformationszeichenfolge GetPassword (); // Anmelding Benutzername String getUnername (); // ob das Konto boolean iscountnonexpired () abläuft; // ob das Konto gefrorene boolean iscountnonlocked () ist; // Ob das Kontokennwort ausgeht, werden im Allgemeinen einige Systeme mit hohen Kennwortanforderungen verwendet. Im Vergleich zum Benutzer muss das Kennwort von Zeit zu Zeit zurückgesetzt werden. // ist das Konto verfügbar? boolean isenabled ();}Wenn wir den Benutzer von Benutzerdetails implementieren, können wir die entsprechenden Parameter über die Benutzerkonstruktor -Methode festlegen
Passwortverschlüsselung und Entschlüsselung
Es gibt eine PasswordEncoder -Schnittstelle in Springsicherheit
public interface passwordEncoder {// Verschlüsseln Sie die Kennwort -String -Encode (charsequence var1); // Bestimmen Sie das Passwort, das mit booleschen Übereinstimmungen übereinstimmt (charsequence var1, String var2);} Wir müssen diese Schnittstelle nur selbst implementieren und in der Konfigurationsdatei konfigurieren.
Hier teste ich es vorübergehend mit einer implementierenden Kursklasse, die standardmäßig bereitgestellt wird
// BrowerSecurityConfig @BeanPublic PasswordEnCoder PassageCoder () {Neue bcryptPasswordEnCoder () zurückgeben; }Verschlüsselungsverwendung:
@ComponentPublic Class MyUSerDetailsService implementiert UserDetailsService {private logger logger = loggerFactory.getLogger (getClass ()); @Autowired Private PasswordEnCoder PasswordEncoder; @Override public userDetails loadUserByUserName (String -Benutzername) löst userernamenotFoundException {logger.info ("Benutzername des Benutzers: {}", Benutzername); String password = passwordEncoder.enCode ("123456"); logger.info ("Passwort: {}", Passwort); // Die Parameter sind: Benutzername, Kennwort, Benutzerberechtigungen User User = New User (Benutzername, Kennwort, Authorityutils.CommaseParatedStringtoAuthorityList ("Admin")); Benutzer zurückgeben; }}Hier verschlüsseln wir einfach 123456. Wir können Tests durchführen und feststellen, dass das Passwort jedes Mal unterschiedlich ist. Dies ist die Rolle des konfigurierten BcryptPasswordCoder.
Personalisierte Benutzerauthentifizierungslogik
Benutzerdefinierte Anmeldeseite
In früheren Tests wurde die Standard -Anmeldeschnittstelle immer verwendet. Ich glaube, dass jedes Produkt sein eigenes Design -Schnittstellendesign hat. Daher erfahren wir, wie Sie die Anmeldeseite in diesem Abschnitt anpassen.
Lassen Sie uns zuerst eine einfache Anmeldeseite schreiben
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Login Page</title></head><body> <h2>Custom Login Page</h2> <form action="/user/login" method="post"> <table> <tr> <td> <td>Username:</td> <td><input type = "text" name = "userername"> </td> </tr> <tr> <td> Kennwort: </td> <td> <Eingabe type = "password" name = "password"> </td> </tr> <tr> <tr> <td colspan = "2"> <button type "> login </td> </td> </td> </td> </td> </td> </td> </td> </td> </td> </td> </td> </td> </td>
Nach Abschluss der Anmeldeseite müssen Sie sie für Spring Security konfigurieren
// BrowerSecurityconfig.java@overrideProtected void configure (httpecurity http) ausreiß page.loginprocessingurl ("/user/login") // benutzerdefinierte Login -Schnittstelle.And () .Authorizequests () // Definieren Sie, welche URLs geschützt werden müssen und welche nicht geschützt werden müssen. .Authenticated () .and () .csrf (). deaktivieren (); // CSRF -Schutz ausschalten}Auf diese Weise werden wir bei Zugriff auf die geschützte Schnittstelle auf die Seite Login.html übertragen
Verwandte verschiedene Arten von Anfragen
Da jetzt die vorderen und hinteren Enden getrennt sind, bietet das hintere Ende Schnittstellen für das Frontend zum Anruf und gibt die JSON -Formatdaten an das Frontend zurück. Nach wie vor wurde die geschützte Schnittstelle aufgerufen und der Seitensprung direkt umgeleitet. Es ist auf der Webseite akzeptabel, aber auf der App -Seite ist es jedoch nicht möglich, daher müssen wir eine weitere Verarbeitung durchführen.
Hier ist eine einfache Idee, die aussortiert wird
Schreiben Sie zunächst einen benutzerdefinierten Controller und springen Sie darauf, wenn die Identitätsauthentifizierung erforderlich ist.
@RestControllerPublic Class BrowsersecurityController {private logger logger = loggerfactory.getLogger (getClass ()); // Caching und Wiederherstellung der ursprünglichen Anforderungsinformationen private RequestCache RequestCache = new httpSessionRequestCache (); // verwendet, um die private RedirectStrategy recirectstrategy zu umleiten = neuer Defaultredirectstrategy (); /** * When identity authentication is required, jump over* @param request * @param response * @return */ @RequestMapping("/authentication/require") @ResponseStatus(code = HttpStatus.UNAUTHORIZED) public BaseResponse requiresAuthenication(HttpServletRequest request, HttpServletResponse response) throws IOException { SavedRequest savedRequest = RequestCache.getRequest (Anfrage, Antwort); if (savedRequest! logger.info ("Die Anforderung, einen Sprung auszulösen, lautet:" + targeturl); if (Stringutils.endswithignoreCase (targeturl, ".html")) {redirectStrategy.sendredirect (Anfrage, Antwort, "/login.html"); }} Neue BaserePonse zurückgeben ("Der zugegriffene Dienst erfordert eine Identitätsauthentifizierung. Bitte führen Sie den Benutzer zur Anmeldeseite"); }}Natürlich muss die Konfigurationsdatei entsprechend geändert werden, sodass ich den Code hier nicht veröffentlichen werde. Es soll die Schnittstelle öffnen.
Erweiterungen:
Hier schreiben wir die Schnittstelle, auf die auf einer Webseite zugegriffen wird, und springen dann zur Seite "/login.html". Tatsächlich können wir es erweitern und die Sprungadresse in der Konfigurationsdatei konfigurieren, die bequemer ist.
Benutzerdefinierte Verarbeitungsanmeldung erfolgreich/fehlgeschlagen
In früheren Tests wurde die Seitenumleitung nach erfolgreichem Anmeldung durchgeführt.
Bei der Trennung von Vorder- und Rücksenden müssen wir möglicherweise die persönlichen Daten des Benutzers an das Frontend zurückgeben, anstatt direkt zu springen. Gleiches gilt für fehlgeschlagenes Login.
Dies beinhaltet zwei Schnittstellen in den AuthenticationSuccessHandler sich und AuthenticationFailureHandler . Wir können diese Schnittstelle implementieren und entsprechend konfigurieren. Natürlich hat das Framework eine Standard -Implementierungsklasse. Wir können diese Implementierungsklasse erben und unser Geschäft anpassen
@Component ("MyAuthEcktiationsuccessHandler") öffentliche Klasse MyAuthenCtiationSuccessHandler erweitert SimpleUrlAuthenticationCcessHandler {private logger logger = loggerfactory.getLogger (getClass ()); @Autowired Private ObjectMapper ObjectMapper; @Override public void onAuthentications -uccess (httpServletRequest Request, HttpServletResponse -Antwort, Authentifizierungsauthentifizierung) löst IOException, ServleTException {logger.info ("Login erfolgreich") aus; response.setContentType ("application/json; CharSet = utf-8"); response.getWriter (). Write (ObjectMapper.WriteValuEasString (Authentifizierung)); }} Hier geben wir eine JSON -String durch die Antwort zurück.
Der dritte Parameter in dieser Methode, Authentication , enthält die Anmeldeinformationen (Benutzerdetails), Sitzungsinformationen, Anmeldeinformationen usw.
@Component ("MyAuthEntiationFailureHandler") öffentliche Klasse MyAuthEntiationFailureHandler erweitert SimpleUrlauthenticationFailureHandler {private logger logger = loggerfactory.getLogger (getClass ()); @Autowired Private ObjectMapper ObjectMapper; @Override public void OnAuthenticationFailure (httpServletRequest -Anfrage, HttpServletResponse -Antwort, Authentifizierungsexception) löst IOException, ServleTException {logger.info ("Login fehlgeschlagen") aus; response.setStatus (httpstatus.internal_server_error.value ()); response.setContentType ("application/json; CharSet = utf-8"); response.getWriter (). Schreiben (ObjectMapper.WriteValuEasString (neue BaserePonse (exception.getMessage ()))); }} Der dritte Parameter in dieser Methode AuthenticationException , enthält Informationen zum Anmeldungsfehler.
In ähnlicher Weise ist es weiterhin erforderlich, es in der Konfigurationsdatei zu konfigurieren. Ich werde hier nicht den gesamten Code veröffentlichen, nur die entsprechenden Anweisungen werden veröffentlicht.
.SuccessHandler (MyAuthenticationsCessHandler) // benutzerdefinierte Anmeldung erfolgreich behandelt.FailureHandler (MyAuthenticationFailureHandler) // Benutzerdefinierte Anmeldungsfehlerhandles
Code
Sie können auf mich klicken, um den vollständigen Code anzuzeigen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.