Este artículo cuenta la historia de Spring Boot Integrating Spring Security para implementar el control de permisos utilizando anotaciones en los métodos y utilizando un servicio de usuarios personalizado para cargar información del usuario de MySQL. Use el cifrado MD5 que viene con seguridad para cifrar la contraseña del usuario. La plantilla de página utiliza el motor Thymeleaf.
Dirección del código fuente: https://github.com/li5454yong/springboot-security.git
1. Introducir dependencias de POM
<Parent> <MoupRoD> org.springframework.boot </proupid> <artifactid> spring-boot-starter-parent </artifactid> <version> 1.4.4.release </lection> </parent> <pendencies> <pendency> <grupo> org.springfamework.boot </groupid> <artifactid> spring-starter-starter-webeb-webeb </artharter> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> </dependency> <Spendency> <MoupRoMID> org.springframework.boot </groupid> <artifactid> spring-boot-starter-thymeleaf </artifactid> </dependency> <papel> <MoupRupid> org.springframework.boot </groupId> <artifactid> spring-boot-starter-starter-sa-sajpa </artifactid> </artifiCid> </artinency </sartifency </artifactInence </artfactid> <MoupRid> org.springframework.boot </groupid> <artifactid> spring-boot-starter-jdbc </artifactid> </pendency> <pendency> <proupid> mysql </groupid> <artifactid> mysql-connector-java </artifactid> <lansione> 5.1.34 </version> </versión> </versión> <MoupRid> com.alibaba </groupid> <artifactid> Druid </arfactid> <versión> 1.0.15 </versión> </pendency> </dependencias>
Aquí, use la agrupación de conexión Druid y los datos de resorte JPA implementan el acceso a la base de datos.
2. Configurar la seguridad de Spring
@Configuration @enablewebmvcsecurity @enableglobalmethodsecurity (prepostenseabled = true) // habilitar anotación de seguridad clase pública webeCurityConfig extiende WebSecurityConfigurerAdapter {@Bean @Override AuthenticationManager AuthenticationManager () arroja excepción {devuelve Super.authenticationicationAger ();); } @Override protegido void configure (httpsecurity http) lanza la excepción {// Permitir a todos los usuarios acceder a "/" y "/home" http.authorizequests () .antmatchers ("/", "/home"). Permitall () // Access a otras direcciones requiere verificación de permissions.AnyRequest (). Authenticated ().).).).). // Especifique la página de inicio de sesión para ser "/login" .loginpage ("/login") .defaultsuccessurl ("/hello") // Después de iniciar sesión exitosa, salta a "/hola" de forma predeterminada. .Permitall () .and () .logout () .logoutsuccessurl ("/home") // La url predeterminada después de la sesión es "/home" .permitall (); } @AUtowired public void configureGlobal (autenticationManagerBuilder Auth) lanza la excepción {auth .UserDetailsService (CustomUserDetailsService ()) .PassWordEncoder (contraseña en la contraseña ()); } / *** Establezca el método de cifrado de la contraseña de usuario en el cifrado MD5* @return* / @Bean public MD5PassWordEncoder contraseñaCoder () {return nuevo MD5PassWordEncoder (); } / *** UserDetailsService personalizado para leer la información del usuario de la base de datos* @return* / @Bean public CustomerDetailsService CustomUserDetailsService () {return New CustomUserDetailsService (); }} Solo se realizan configuraciones básicas aquí, configurando URL de inicio de sesión, URL que salta después de iniciar sesión es exitosa y URL que salta después del inicio de sesión. Usar la anotación @enableGlobalMethodSecurity (prepostenable = true) puede habilitar la anotación de la seguridad. Podemos usar @peauthorize y @prefilter en métodos que requieren permisos de control.
3. Servicio de usuario de usuario personalizado
public class CustomUserDetailsService implementa UserDetailsService {@aUtowired // Domain Service Clase private Suserservice WaitService; @Override Public UserDetails LoadUserByUserName (String UserName) lanza usernAmenotFoundException {// Suser corresponde a la tabla de usuario en la base de datos, que es la tabla que finalmente el usuario y la contraseña, que se puede personalizar // este ejemplo en Suser como el nombre de usuario: Suser User = SuserService.FinduserByEm. if (user == NULL) {lanzar New UserNaMenotFoundException ("Nombre de usuario" + Nombre de usuario + "No encontrado"); } // SecurityUser implementa UserDetails y mapea el correo electrónico de Suser al nombre de usuario SecurityUser SecurityUser = New SecurityUser (usuario); Colección <simplegrantedAuthority> autorities = new ArrayList <InsprantedAuthority> (); autoridades.add (new SimpleGrantedAuthority ("rol_admin")); devolver SecurityUser; }}Aquí solo necesita implementar la interfaz UserDetailsService, reescribir el método LoadUserByUserName y recuperar la información del usuario de la base de datos. Finalmente, se devuelve una clase de implementación de UserDetails.
4. Defina la configuración de manejo de errores
@ConfigurationPublic Class ErrorPageConfig {@Bean Public IncreddedServletContainerCustomizer IncreddedServletContainerCustomizer () {return new MyCustomizer (); } MyCustomizer de clase estática privada implementa IncreddedServletContainerCustomizer {@Override public Void personalizar (configurableMbedDedServletContainer Container) {Container.adderrorpages (nueva ErrorPage (httpStatus.Forbidden, "/403")); }}}Cuando ocurra un error de acceso, salte a "/403".
5. Interfaz del controlador
@ControllerPublic Class indexController {@Resource private Suserservice Suserservice; @RequestMapping ("/Home") public String Home () {return "Home"; } @PreAuthorize ("HasRole ('User')") @RequestMapping (valor = "/admin", método = requestMethod.get) public String toAdmin () {return "HelloAdmin"; } @RequestMapping ("/Hello") public String Hello () {return "Hello"; } @RequestMapping ("/login") public String Login () {return "Login"; } @RequestMapping ("/") public String root () {return "índice"; } @RequestMapping ("/403") Public String Error () {return "403"; }}@PreAuthorize ("HasRole ('User')") se usa en el método Toadmin (), lo que indica que debe tener el rol de usuario para acceder a este método. Si desea controlar el nivel de permisos, puede usar @PreAuthorize ("HasperMission ()"). Este es solo uno de los usos. Para obtener más métodos de uso, puede leer la documentación oficial. Cabe señalar que el prefijo de rol predeterminado de Spring Security es "Role_", que se ha agregado de forma predeterminada cuando se usa el método Hasrole. Por lo tanto, nuestro papel de usuario en la base de datos debe ser "role_user", y el prefijo del usuario "rol_" se agrega antes del usuario.
6. Prueba
Inicie el proyecto y visite http: // localhost: 1130/inicio de sesión
Haga clic para iniciar sesión e ingresar "/hola"
Haga clic para saltar a la página Administrador
En el fondo de la URL "/Admin" correspondiente al método "Usuario", los usuarios deben tener el rol de "Usuario". El usuario que inició sesión también está configurado en la base de datos para tener este rol.
Ahora modificamos el papel del usuario en la base de datos y lo cambiamos a "rol_admin". Después de iniciar sesión, inicie sesión nuevamente, haga clic en el botón "Vaya a la página Administrador" nuevamente y saltará a la página siguiente.
Debido a que ahora no hay permiso de "usuario", se lanzó una excepción durante el acceso, y se interceptó y se redirigió a "/403".
7. Post Access, código de error 403
Primero, cambiar "/admin" para publicar la solicitud
@PreAuthorize ("HasRole ('User')") @RequestMapping (valor = "/admin", método = requestMethod.post) public String toAdmin () {return "HelloAdmin"; }Cambie el método de solicitud del botón "Vaya a la página Administrador" desde la expresión del formulario original. Obtenga el envío a la envío de AJAX POST. En cuanto a por qué no nos enviamos usando la publicación del formulario, hablaremos de ello más tarde. Modificar el código primero
<body> <h1 th: inline = "text"> hello [[$ {#httpservletRequest.remoteUser}]]! </h1> <!-<form th: action = "@{/logOut}" método = "post"> <input type = "enviar" value = "firmar"/> </form> <formul th: type = "Subt" th: value = "vaya a la página del administrador"/> </form>-> <a th: href = "@{/admin}" rel = "externo nofollow"> vaya a la página de usuario del administrador </a> <input typy = "shipt" onclick = "testPost ()" th: value = "vaya a la página del administrador"/> </bully> <sciot> script (script (script (script ((script ((script ((script ((script ((script ((script ((script ((script ((script ((script ((script (script) ((script) $ .AJAX ({url: "/admin", type: 'post', éxito: function (data) {}}); } </script> Haga clic en el botón "Vaya a la página del administrador" y puede ver lo siguiente en la plataforma de depuración
Esto se debe a que el marco evita que se produzca CSRF (falsificación de solicitud de solicitud de sitio cruzado de falsificación de solicitud de sitio cruzado), lo que limita la mayoría de los métodos, excepto.
Aquí hay una solución:
Primero agregue el siguiente contenido en la etiqueta.
<meta name = "_ csrf" th: content = "$ {_ csrf.token}"/> <meta name = "_ csrf_hader" th: content = "$ {_ csrf.headername}"/> Mientras se agregue esta token, el fondo verificará la corrección de este token. Si es correcto, aceptará el acceso posterior.
Luego agregue el siguiente código en el código AJAX:
var token = $ ('meta [name = "_ csrf"]'). attr ("content"); var encabezado = $ ('meta [name = "_ csrf_hader"]'). attr ("content"); $ (document) .AJAXSEND (function (e, xhr, opt) {xhr.setrequester (header, token);}; De esta manera, puede acceder a él normalmente utilizando Post, Eliminar y otros métodos.
El mencionado anteriormente utilizando el método de publicación de formulario para enviar. Puede ver viendo el código fuente de la página.
El marco inserta automáticamente un campo oculto en el formulario del formulario, y el valor del valor es ese token, por lo que el uso del formulario del formulario para enviar una solicitud de publicación puede aprobarse directamente, y si lo envía de manera Ajax, ese código debe agregarse.
Bien, eso se trata de este artículo. Más adelante habrá artículos sobre cómo usar la seguridad de primavera para controlar los permisos en el estilo API REST.
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.