1. Introducción a Spring Security
Spring Security es un marco de seguridad que brinda protección de seguridad declarativa para aplicaciones basadas en Spring. Proporciona una solución de seguridad completa que maneja la verificación de identidad y la autorización a nivel de solicitud web y nivel de invocación de método. Debido a que se basa en el marco Spring, Spring Security hace un uso completo de la inyección de dependencia y las tecnologías orientadas a aspectos.
Spring Security resuelve principalmente los problemas de seguridad desde dos aspectos:
-
Nivel de solicitud web : use los filtros en la especificación de Servlet para proteger las solicitudes web y restringir el acceso a nivel de URL.
-
Nivel de invocación de métodos : use Spring AOP para proteger las invocaciones de métodos, asegurándose de que solo los usuarios con los permisos adecuados puedan acceder a los métodos protegidos.
Si desea tener una comprensión profunda de los conceptos relacionados y los principios de implementación de Spring Security, puede hacer clic en el portal == " Principios básicos de Spring Security
En segundo lugar, la demostración de seguridad a nivel de solicitud web de Spring Security
1. Cree un nuevo proyecto Spring y agregue dependencias springsecurity al archivo pom.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. Cree una clase de configuración para Spring Security
package com.spring.security.springsecurity.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity //启用Web安全功能
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
//访问"/"和"/home"路径的请求都允许
.antMatchers("/", "/home","/staff","/staff/*")
.permitAll()
//而其他的请求都需要认证
.anyRequest()
.authenticated()
.and()
//修改Spring Security默认的登陆界面
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
//基于内存来存储用户信息
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("user").password(new BCryptPasswordEncoder().encode("123")).roles("USER").and()
.withUser("admin").password(new BCryptPasswordEncoder().encode("456")).roles("USER","ADMIN");
}
}
Análisis de código:
Anotación @EnableWebSecurity: habilite la función de seguridad web (pero es inútil por sí misma, la clase de configuración Spring Security también necesita implementar WebSecurityConfigurer o heredar la clase WebSecurityConfigurerAdapter, esta última se usa en esta demostración porque es más fácil de configurar y usar).
Anotación @EnableWebMvcSecurity: en desuso en Spring 4.0.
Clase WebSecurityConfigurerAdapter: puede especificar los detalles de la seguridad web sobrecargando los tres métodos configure() de esta clase.
1. configure(WebSecurity): al sobrecargar este método, se puede configurar la cadena de filtros de Spring Security.
2. configure (HttpSecurity): al anular este método, puede configurar cómo proteger las solicitudes a través de los interceptores.
Cómo configurar la ruta de protección
método
puede hacer
acceso (cadena)
Permite el acceso si la expresión SpEL dada se evalúa como verdadera
anónimo()
Permitir el acceso de usuarios anónimos
autenticado()
Permitir que los usuarios autenticados accedan
negar todo ()
Denegar incondicionalmente todo acceso
totalmente autenticado()
Si el usuario está completamente autenticado (no autenticado por la función Recordarme), se permite el acceso
tieneCualquierAutoridad(Cadena…)
Permitir el acceso si el usuario tiene uno de los permisos dados
tiene Cualquier Rol (Cadena…)
Permitir el acceso si el usuario tiene uno de los roles dados
tiene autoridad (cadena)
Permitir el acceso si el usuario tiene el permiso dado
tiene dirección IP (cadena)
Permitir el acceso si la solicitud proviene de la dirección IP dada
tiene rol (cadena)
Permitir el acceso si el usuario tiene el rol dado
no()
Negar los resultados de otros métodos de acceso
permitAll()
acceso incondicional
Recuérdame()
Permitir el acceso si el usuario está autenticado por la función Recordarme
Todas las expresiones SpEL admitidas por Spring Security son las siguientes:
expresión segura
Resultados de cálculo
autenticación
Objeto de autenticación de usuario
negar todo
el resultado siempre es falso
hasAnyRole(lista de roles)
verdadero si al usuario se le otorga cualquiera de los permisos especificados
tiene papel (papel)
verdadero si al usuario se le ha otorgado el permiso especificado
hasIpAddress(Dirección IP)
Dirección de usuario
esAnónimo()
es un usuario anonimo
está autenticado()
no es un usuario anonimo
está completamente autenticado
Autenticación no anónima ni recordar-me
esRecordame()
Certificación Recuérdame
permitAll
siempre cierto
principal
Objeto de información principal del usuario
3. configure (AuthenticationManagerBuilder): al sobrecargar este método, se puede configurar el servicio de detalles del usuario (detalles del usuario).
Cómo configurar los detalles del usuario
método
describir
cuenta caducada (booleano)
Define si la cuenta ha caducado
cuenta bloqueada (booleano)
Define si la cuenta está bloqueada
y()
para configuración de conexión
autoridades (autoridad otorgada…)
Otorgar uno o más permisos a un usuario
autoridades(Lista)
Otorgar uno o más permisos a un usuario
autoridades(String…)
Otorgar uno o más permisos a un usuario
credenciales expiradas (booleano)
Define si la credencial ha caducado
deshabilitado (booleano)
Define si la cuenta ha sido deshabilitada
contraseña (cadena)
Definir la contraseña del usuario
roles (Cadena…)
Otorgar a un usuario uno o más roles
Hay tres formas de almacenar la información del usuario:
**1. Usar almacenamiento de usuario basado en memoria: **A través inMemoryAuthentication()
de métodos, podemos habilitar, configurar y poblar arbitrariamente el almacenamiento de usuario basado en memoria. Y podemos llamar withUser()
al método para agregar un nuevo usuario al almacén de usuarios en memoria, el parámetro de este método es username
. withUser()
El método devuelve UserDetailsManagerConfigurer.UserDetailsBuilder, que proporciona varios métodos para seguir configurando al usuario, incluidos métodos para establecer la contraseña del usuario password()
y otorgar uno o más permisos de función para un usuario determinado roles()
. Tenga en cuenta que el roles()
método es authorities()
una abreviatura de método. roles()
Los valores dados al método se anteponen con un ROLE_
prefijo y se otorgan al usuario como un permiso. Por lo tanto, la autoridad del usuario del código de apelación es: ROLE_USER,ROLE_ADMIN。而
con la ayuda del passwordEncoder()
método para especificar un codificador de contraseña (codificador), podemos cifrar y almacenar la contraseña del usuario.
**2.Autenticación basada en tablas de bases de datos: **Los datos de usuario generalmente se almacenan en una base de datos relacional y se accede a ellos a través de JDBC. Para configurar Spring Security para usar un almacén de usuarios respaldado por JDBC, podemos usar el jdbcAuthentication()
método y configurar su fuente de datos para que podamos acceder a la base de datos relacional.
**3. Autenticación basada en LDAP: **Para que Spring Security use la autenticación basada en LDAP, podemos usar el ldapAuthentication()
método.
3. Código de capa del controlador y código front-end
El código de SecurityController es el siguiente:
package com.spring.security.springsecurity.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class SecurityController {
@GetMapping(value = {"/home","/"})
public String home(){
return "home";
}
@GetMapping(value = "/hello")
public String hello(){
return "hello";
}
@GetMapping(value = "/login")
public String login(){
return "login";
}
}
inicio.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example</title>
</head>
<body>
<h1>Welcome!</h1>
<p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
</body>
</html>
hola.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
<input type="submit" value="Sign Out"/>
</form>
</body>
</html>
iniciar sesión.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example </title>
</head>
<body>
<div th:if="${param.error}">
Invalid username and password.
</div>
<div th:if="${param.logout}">
You have been logged out.
</div>
<form th:action="@{/login}" method="post">
<div><label> User Name : <input type="text" name="username"/> </label></div>
<div><label> Password: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>
4. Resultados y análisis de la operación
Cuando visitamos localhost:8080/hello directamente, la página saltará a http://localhost:8080/login , esto se debe a que la clase SecurityConfig configura solo las solicitudes para las rutas "/" y "/home" sin iniciar sesión. , mientras que otras solicitudes requieren autenticación. (Nota: he cambiado el puerto aquí a 8081 porque he realizado ajustes. Puede acceder al puerto 8080 como de costumbre).
En este punto, ingresamos a la interfaz de inicio de sesión, configuramos el nombre de usuario y la contraseña según el almacenamiento de memoria en SecurityConfig, y saltaremos con éxito a la interfaz de saludo.
Tres, demostración de seguridad de nivel de invocación del método de Spring Security
Spring Security proporciona tres anotaciones de seguridad diferentes:
- La propia anotación @Secured de Spring Security;
- @RolesAllowed anotación de JSR-250;
- Anotaciones basadas en expresiones, incluidas @PreAuthorize, @PostAuthorize, @PreFilter y @PostFilter.
anotación
describir
@preautorizar
Restrinja el acceso a métodos en función de la evaluación de expresiones antes de la invocación del método
@PostAutorizar
Se permite la invocación de métodos, pero se lanzará una excepción de seguridad si la expresión se evalúa como falsa
@postfiltro
Se permite la invocación del método, pero el resultado del método debe filtrarse por expresión
@prefiltro
Se permiten las llamadas a métodos, pero los valores de entrada deben filtrarse antes de ingresar al método
1. Habilite la seguridad del método basado en anotaciones
En Spring, si desea habilitar la seguridad del método basado en anotaciones, la clave es usar @EnableGlobalMethodSecurity en la clase de configuración, como:
package com.spring.security.springsecurity.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
Aquí establecemos secureEnabled = true, luego Spring creará un punto de corte y evitará que los métodos anotados con @Secured ingresen al aspecto. De manera similar, jsr250Enabled = true y prePostEnabled = true, habilitan respectivamente @RolesAllowed y anotaciones basadas en expresiones.
Después de configurar la clase MethodSecurityConfig en este punto, podemos agregar un método al SecurityController basado en el código de apelación:
@GetMapping(value = "/admin")
@Secured("ROLE_ADMIN")
public String admin(){
return "admin";
}
La interfaz admin.html es la siguiente:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>admin</title>
</head>
<body>
<h1>admin page</h1>
</body>
</html>
En este punto, ¿cómo accedemos a la ruta http://localhost:8081/admin como usuario usuario y se producirá un error 403?
Si accede a la ruta http://localhost:8081/admin como usuario administrador, se mostrará la siguiente interfaz, lo que indica un acceso exitoso.