Introducción básica de Spring Security
No daré demasiada introducción a la seguridad de primavera aquí. Para más detalles, consulte la documentación oficial.
Solo hablaré sobre las funciones centrales de SpringSecurity:
Construcción del entorno básico
Aquí usamos SpringBoot como el marco básico del proyecto. Estoy usando el método Maven para la gestión de paquetes, por lo que aquí primero damos el método de integrar la seguridad de Spring.
<Spendencies> ... <Spendency> <MoupRoMID> org.springframework.boot </groupId> <artifactId> Spring-Boot-Starter-Security </artifactId> </pendency> ... </pendencs>
Luego establezca una interfaz de solicitud de capa web
@RestController @requestmapping ("/user") public class UserController {@getMapping public String getUsers () {return "Hello Spring Security"; }}A continuación, puede ejecutar el proyecto directamente y llamar a la interfaz para ver el efecto.
Llamar a través de la página web
Primero hacemos que la interfaz llame a través del navegador y accedamos directamente a http: // localhost: 8080/usuario. Si se puede acceder normalmente a la interfaz, entonces se debe mostrar "Hello Spring Security".
Pero no podemos acceder a él normalmente, y aparece el cuadro de entrada de autenticación en la siguiente figura
Esto se debe a que en SpringBoot, la seguridad de resorte predeterminada es efectiva. En este momento, las interfaces están protegidas y debemos pasar la verificación para acceder a ellas normalmente. Spring Security proporciona un usuario predeterminado, el nombre de usuario es usuario y la contraseña se genera automáticamente cuando se inicia el proyecto.
Cuando verificamos el registro de inicio del proyecto, encontraremos el siguiente registro
Uso de contraseña de seguridad predeterminada: 62CCF9CA-9FBE-4993-8566-8468CC33C28C
Por supuesto, la contraseña que ve debe ser diferente de la mía. Iniciamos directamente con el usuario y la contraseña en el registro de inicio.
Después de iniciar sesión con éxito, salta a la página donde la interfaz se llama normalmente.
Si no desea habilitar la seguridad de Spring desde el principio, puede configurar lo siguiente en el archivo de configuración:
# Security Enable Security.Basic.enabled = false
El cuadro de inicio de sesión que acabamos de ver fue proporcionado por SpringSecurity, que se llama httpbasiclogin. No es lo que queremos en nuestro producto. Nuestro front-end generalmente realiza la verificación de inicio de sesión del usuario a través del envío de formularios, por lo que necesitamos personalizar nuestra propia lógica de autenticación.
Personalizar la lógica de autenticación del usuario
Cada sistema debe tener su propio conjunto de sistemas de usuario, por lo que necesitamos personalizar nuestra propia lógica de autenticación e interfaz de inicio de sesión.
Aquí necesitamos configurar SpringSecurity en consecuencia
@ConfigurationPublicCublic clase BrowersecurityConfig extiende WebSecurityConfigurerAdapter {@Override Proteged void Configure (httpsecurity http) lanza la excepción {http.formlogin () // define la página de inicio de sesión que se transfiere cuando el usuario sea necesario para iniciar sesión. Y () .authorizequests () / / / / / / / / / es decir que se transfiera. protegido y que no necesita ser protegido. AnyRequest () // Para cualquier solicitud, puede acceder a .authenticated (); }}A continuación, configure la lógica de autenticación del usuario, porque tenemos nuestro propio sistema de usuario.
@ComponentPublic MyUserDetailsService implementa UserDetailSService {private logger logger = loggerFactory.getLogger (getClass ()); @Override Public UserDetails LoadUserByUserName (String UserName) lanza usernAmenotFoundException {logger.info ("Nombre de usuario del usuario: {}", username); // TODO Según el nombre de usuario, encuentre la contraseña correspondiente y encapsula la información del usuario y la devolución. Los parámetros son: nombre de usuario, contraseña, permisos de usuario user usuario = nuevo usuario (nombre de usuario, "123456", autoryUtils.commasaSeParatedStringToAuthorityList ("Admin")); devolver el usuario; }} No realizamos demasiada verificación aquí. El nombre de usuario se puede completar a voluntad, pero la contraseña debe ser "123456" para que podamos iniciar sesión con éxito.
Al mismo tiempo, podemos ver que el tercer parámetro del objeto de usuario aquí representa los permisos del usuario actual, y lo establecemos en "Admin".
Ejecute el programa para probarlo, y encontrará que la interfaz de inicio de sesión ha cambiado.
Esto se debe a que configuramos http.formLogin() en el archivo de configuración
Completemos un usuario aquí y luego complete una versión incorrecta (no 123456). Esto provocará un error de verificación:
Al mismo tiempo, en la consola, el usuario que acaba de completar cuando inicie sesión también se imprimirá.
Ahora intentemos iniciar sesión con la contraseña correcta. Puede encontrar que pasará la verificación y saltará a la página de llamadas de interfaz correcta.
Deceta de usuarios
Justo ahora, cuando estábamos escribiendo MyUserDetailsService , implementamos un método y devolvimos un UserDetails . Este usuario de UserDeta es un objeto que encapsula la información del usuario, que contiene siete métodos
Interfaz pública Los usuarios de usuario extienden serializable {// recopilación de información de permiso encapsulado <? extiende a GrantedAuthority> getAuthorities (); // Información de contraseña String String getPassword (); // Iniciar sesión String de nombre de usuario getUsername (); // si la cuenta expira boolean isaccountnonexpired (); // si la cuenta está congelada boolean isaccountnonlocked (); // Si la contraseña de la cuenta expira, generalmente algunos sistemas con altos requisitos de contraseña lo utilizarán. En comparación con el usuario, se requiere restablecer la contraseña de vez en cuando es boolean iscredentialsnonexpired (); // ¿Está disponible la cuenta? boolean isEnabled ();}Cuando devuelvamos el usuario de la clase de implementación de UserDetails, podemos establecer los parámetros correspondientes a través del método del constructor de usuarios
Cifrado de contraseña y descifrado
Hay una interfaz de contraseña en SpringSecurity
Interfaz pública PasswordEncoder {// Cifre el codificador de cadena de contraseña (CharSECHENCE VAR1); // Determinar la contraseña para coincidir con los coincidencias booleanos (CharSequence Var1, String Var2);} Solo necesitamos implementar esta interfaz nosotros mismos y configurarla en el archivo de configuración.
Aquí lo probaré temporalmente con una clase de implementación proporcionada por defecto
// BROWERSECURITYCONFIG @BeanPublic PasswordEncoder PasswordEncoder () {return new BCryptPassPassWordEnder (); }Uso de cifrado:
@ComponentPublic MyUserDetailsService implementa UserDetailSService {private logger logger = loggerFactory.getLogger (getClass ()); @AUTOWIREDIREDIRD PasswordEncoder PasswordEncoder; @Override Public UserDetails LoadUserByUserName (String UserName) lanza usernAmenotFoundException {logger.info ("Nombre de usuario del usuario: {}", username); String Password = PasswordEncoder.Encode ("123456"); logger.info ("contraseña: {}", contraseña); // Los parámetros son: nombre de usuario, contraseña, permisos de usuario usuarios de usuario = nuevo usuario (nombre de usuario, contraseña, autorutionUtils.CommasaSeParatedStringToAuthorityList ("Admin")); devolver el usuario; }}Aquí simplemente cifraremos 123456. Podemos realizar pruebas y encontrar que la contraseña impresa cada vez es diferente. Este es el papel del BcryptPassWordEncoder configurado.
Lógica de autenticación de usuario personalizada
Página de inicio de sesión personalizada
En las pruebas anteriores, siempre se ha utilizado la interfaz de inicio de sesión predeterminada. Creo que cada producto tiene su propio diseño de interfaz de inicio de sesión, por lo que aprenderemos sobre cómo personalizar la página de inicio de sesión en esta sección.
Vamos a escribir primero una página de inicio de sesión simple
<! Doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> página de inicio de sesión </title> </head> <body> <h2> Página de inicio de sesión personalizada </h2> <Form Action = "/user/Login" Method = "Publica"> <table> <tr> <TD> <TD> type = "text" name = "username"> </td> </tr> <tr> <td> contraseña: </td> <td> <input type = "contraseña" name = "contraseña"> </td> </tr> <tr> <td colspan = "2"> <button type = "enviar"> login </booty> </td> </tr> </table> </form> </body> </html>
Después de completar la página de inicio de sesión, debe configurarla para SpringSecurity
// browersecurityconfig.java@overrideprotected void configure (httpsecurity http) lanza una excepción {http.formlogin () // Defina la página de inicio de sesión que se transferirá cuando el usuario necesita iniciar sesión .Loginpage ("/login.html") // establece el inicio de sesión de la sesión de inicio de sesión cuando el usuario necesita iniciar sesión. Page.loginProcessingUrl ("/User/Login") // Interface de inicio de sesión personalizado.And () .AuthorizeRequests () // Defina qué URL deben protegerse y cuáles no deben protegerse. .authenticated () .and () .csrf (). Disable (); // Apague la protección CSRF}De esta manera, cada vez que accedamos a la interfaz protegida, seremos transferidos a la página Login.html
Manejar diferentes tipos de solicitudes
Debido a que ahora, los extremos delanteros y traseros están generalmente separados, el extremo posterior proporciona interfaces para que la parte delantera llame y devuelva los datos de formato JSON a la parte delantera. Como antes, se llamó a la interfaz protegida y el salto de la página se redirigió directamente. Es aceptable en el lado web, pero no es posible en el lado de la aplicación, por lo que debemos hacer un procesamiento adicional.
Aquí hay una simple idea de clasificación
Primero, escriba un controlador personalizado y salte cuando se requiere autenticación de identidad.
@RestControllerPublic BROWSERSECURITYController {private logger logger = loggerFactory.getLogger (getClass ()); // almacenamiento en caché y recuperación de información de solicitud original requestCache requestCache = new httpsessionRequestCache (); // se usa para redirigir redirectStrategy privado redirectStrategy = new DeFaulTredirectStrategy (); /** * Cuando se requiere la autenticación de identidad, salte a * @param solicitud * @param respuesta * @return */@RequestMapping ("/autenticación/requerir") @ResponseStatus (code = httpstatus.UNAUTHORIZED) public BaseSponse Requerido (httPservEltRequest Solicitud, httTpSeServeSception) sholeSceptation {SaveDREQUINCECTIV savedRequest = requestCache.getRequest (solicitud, respuesta); if (saveDRequest! = null) {string TargetUrl = SavedRequest.getedirectURL (); logger.info ("La solicitud para activar un salto es:" + TargetUrl); if (stringUtils.endswithignorecase (TargetUrl, ".html")) {redirectStrategy.sendedirect (solicitud, respuesta, "/login.html"); }} return New BaseSponse ("El servicio accedido requiere autenticación de identidad, por favor guíe al usuario a la página de inicio de sesión"); }}Por supuesto, el archivo de configuración debe modificarse en consecuencia, por lo que no publicaré el código aquí. Es para abrir la interfaz.
Extensiones:
Aquí escribimos la interfaz a la que se accede desde una página web, luego saltamos a la página "/Login.html". De hecho, podemos expandirlo y configurar la dirección de salto al archivo de configuración, que será más conveniente.
Iniciar sesión de procesamiento personalizado exitoso/fallido
En pruebas anteriores, la redirección de la página se realizó después de un inicio de sesión exitoso.
En el caso de la separación de los extremos frontales y traseros, si iniciamos sesión con éxito, es posible que necesitemos devolver la información personal del usuario a la parte delantera en lugar de saltar directamente. Lo mismo es cierto para el inicio de sesión fallido.
Esto implica dos interfaces en Spring Security AuthenticationSuccessHandler y AuthenticationFailureHandler . Podemos implementar esta interfaz y configurarla en consecuencia. Por supuesto, el marco tiene una clase de implementación predeterminada. Podemos heredar esta clase de implementación y personalizar nuestro negocio
@Component ("myauthenctiationsuccessHandler") clase pública myauthenctiationsuccessHandler extiende simplistenticationsuccesshandler {private logger logger = loggerFactory.getLogger (getClass ()); @AUtowired private ObjectMapper ObjectMapper; @Override public void onAuthenticationSuccess (solicitud httpservletRequest, respuesta httpServletResponse, autenticación de autenticación) lanza ioexception, servletException {logger.info ("inicio de sesión exitoso"); respuesta.setContentType ("Aplicación/JSON; Charset = UTF-8"); Response.getWriter (). Write (ObjectMapper.WriteValueAsString (autenticación)); }} Aquí devolvemos una cadena JSON a través de la respuesta.
El tercer parámetro en este método, Authentication , contiene la información del usuario de inicio de sesión (colas de usuario), información de sesión, información de inicio de sesión, etc.
@Component ("myauthenctiationFailureHandler") clase pública myauthenctiationFailureHandler extiende SimpleUrlauthenticationFailureHandler {private logger logger = loggerFactory.getLogger (getClass ()); @AUtowired private ObjectMapper ObjectMapper; @Override public void onAuthenticationFailure (solicitud httpservletRequest, respuesta httpservletResponse, excepción de EXCEPTION de autenticación) lanza ioexception, servletException {logger.info ("inicio de sesión fallido"); Response.SetStatus (httpstatus.internal_server_error.value ()); respuesta.setContentType ("Aplicación/JSON; Charset = UTF-8"); Response.getWriter (). Write (ObjectMapper.WriteValueAsString (new BaseResponse (excepción.getMessage ()))); }} El tercer parámetro en este método AuthenticationException , incluye información sobre la falla de inicio de sesión.
Del mismo modo, todavía es necesario configurarlo en el archivo de configuración. No publicaré todo el código aquí, solo se publican las declaraciones correspondientes.
.SuccessHandler (myauthenticationsuccesshandler) // inicio de sesión personalizado manejas con éxito.
Código
Puede hacer clic en mí para ver el código completo
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.