Histoire de base et systématique Histoire de certification / d'autorisation Histoire Remember-Me Histoire CSRF Histoire de gestion de session Parler de l'en-tête de réponse Histoire CORS L'histoire de Run-As L'histoire d'ACL Test story Parlez de la coopération avec MVC et Boot
Édition supplémentaire Ce que Spring Security peut et ne peut pas faire
Spring Security prend en charge le contrôle d'accès au niveau de la méthode en plus du contrôle d'accès en spécifiant une URL. Il est recommandé que le contrôle d'accès au niveau de la méthode soit effectué au niveau de la couche service, plutôt que de se fier uniquement au contrôle d'accès basé sur l'URL.
http://docs.spring.io/spring-security/site/docs/4.2.1.RELEASE/reference/htmlsingle/#request-matching
In practice we recommend that you use method security at your service layer, to control access to your application, and do not rely entirely on the use of security constraints defined at the web-application level. [Français] En pratique, nous vous recommandons d'utiliser la méthode de sécurité au niveau de la couche service pour contrôler l'accès à votre application et de ne pas faire totalement confiance à l'utilisation des contraintes de sécurité définies au niveau de l'application Web.
URLs change and it is difficult to take account of all the possible URLs that an application might support and how requests might be manipulated. [Français] Il est difficile d'envisager comment gérer toutes les URL et demandes que votre application prend en charge lorsque l'URL change.
Security defined at the service layer is much more robust and harder to bypass, so you should always take advantage of Spring Security’s method security options. [Français] La sécurité définie au niveau de la couche service est plus robuste et difficile à contourner [^ 5]. Par conséquent, vous devez toujours profiter des options de sécurité des méthodes de Spring Security.
[^ 5]: contournement des contrôles de sécurité
MyMethodSecurityService.java
package sample.spring.security.service;
import org.springframework.security.access.prepost.PreAuthorize;
public class MyMethodSecurityService {
@PreAuthorize("hasAuthority('ADMIN')")
public String execute() {
return "Hello Method Security!!";
}
}
MyMethodSecurityServlet.java
package sample.spring.security.servlet;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import sample.spring.security.service.MyMethodSecurityService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/method-security")
public class MyMethodSecurityServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(req.getServletContext());
MyMethodSecurityService service = context.getBean(MyMethodSecurityService.class);
PrintWriter writer = resp.getWriter();
try {
writer.println(service.getMessage());
} catch (AccessDeniedException e) {
writer.println(e.getMessage());
} finally {
writer.close();
}
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<sec:global-method-security pre-post-annotations="enabled" />
<bean class="sample.spring.security.service.MyMethodSecurityService" />
<sec:http>
<sec:intercept-url pattern="/login" access="permitAll" />
<sec:intercept-url pattern="/**" access="isAuthenticated()" />
<sec:form-login />
<sec:logout />
</sec:http>
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="user" password="user" authorities="USER" />
<sec:user name="admin" password="admin" authorities="ADMIN" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
Java Configuration
MySpringSecurityConfig.java
package sample.spring.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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 sample.spring.security.service.MyMethodSecurityService;
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin();
}
@Bean
public MyMethodSecurityService myMethodSecurityService() {
return new MyMethodSecurityService();
}
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password("user")
.authorities("USER")
.and()
.withUser("admin")
.password("admin")
.authorities("ADMIN");
}
}
Le haut est lorsque vous vous connectez en tant que ʻutilisateur, et le bas est lorsque vous vous connectez en tant que ʻadmin
.
applicationContext.xml
<sec:global-method-security pre-post-annotations="enabled" />
MySpringSecurityConfig.java
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
<global-method-security>
et définissez pre-post-annotations =" enabled "
--Pour la configuration Java, ajoutez @ EnableGlobalMethodSecurity
et définissez prePostEnabled = true
MyMethodSecurityService.java
@PreAuthorize("hasAuthority('ADMIN')")
public String getMessage() {
return "Hello Method Security!!";
}
--Annotez la méthode à laquelle vous souhaitez appliquer le @ PreAuthorize
--Pour value
, spécifiez le contrôle d'accès basé sur les expressions de la même manière que pour ʻaccess
of <intercept-url>
.
MyMethodSecurityService.java
package sample.spring.security.service;
import org.springframework.security.access.prepost.PostAuthorize;
public class MyMethodSecurityService {
@PostAuthorize("returnObject == 'hoge'")
public String getMessage(String parameter) {
System.out.println("parameter = " + parameter);
return parameter;
}
}
MyMethodSecurityServlet.java
package sample.spring.security.servlet;
...
@WebServlet("/method-security")
public class MyMethodSecurityServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(req.getServletContext());
MyMethodSecurityService service = context.getBean(MyMethodSecurityService.class);
PrintWriter writer = resp.getWriter();
try {
String parameter = req.getParameter("parameter");
writer.println(service.getMessage(parameter));
} catch (AccessDeniedException e) {
writer.println(e.getMessage());
} finally {
writer.close();
}
}
}
Les paramètres sont les mêmes que [précédent](# method-security-pre-authorize).
Accédez à / method-security? Parameter = hoge
Sortie serveur
parameter = hoge
Accédez à / method-security? Parameter = fuga
Sortie serveur
parameter = fuga
MyMethodSecurityService.java
@PostAuthorize("returnObject == 'hoge'")
public String getMessage(String parameter) {
System.out.println("parameter = " + parameter);
return parameter;
}
--Si vous annotez avec @ PostAuthorize
, la vérification sera effectuée après l'exécution de la méthode.
value
ainsi que @ PreAuthorize
returnObject
.MyMethodSecurityService.java
package sample.spring.security.service;
import org.springframework.security.access.prepost.PreAuthorize;
public class MyMethodSecurityService {
@PreAuthorize("#strValue == 'aaa' and #intValue == 1")
public String getMessage(String strValue, int intValue) {
return "strValue=" + strValue + ", intValue=" + intValue;
}
}
MyMethodSecurityServlet.java
package sample.spring.security.servlet;
...
@WebServlet("/method-security")
public class MyMethodSecurityServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(req.getServletContext());
MyMethodSecurityService service = context.getBean(MyMethodSecurityService.class);
PrintWriter writer = resp.getWriter();
try {
String strValue = req.getParameter("strValue");
int intValue = Integer.parseInt(req.getParameter("intValue"));
writer.println(service.getMessage(strValue, intValue));
} catch (AccessDeniedException e) {
writer.println(e.getMessage());
} finally {
writer.close();
}
}
}
Accédez à / method-security? StrValue = abc & intValue = 1
Accédez à / method-security? StrValue = aaa & intValue = 1
MyMethodSecurityService.java
@PreAuthorize("#strValue == 'aaa' and #intValue == 1")
public String getMessage(String strValue, int intValue) {
Le nom du paramètre de la méthode ne peut pas être pris par réflexion s'il s'agit de Java 7 ou moins.
Par contre, dans le cas de Java 8 ou supérieur, si l'option -parameters
est spécifiée au moment de la compilation, les noms de paramètres peuvent être pris par réflexion /api/java/lang/reflect/Parameter.html).
Spring fournit des solutions pour différents noms de paramètres pour gérer ces situations.
python
package sample.spring.security.service;
import org.springframework.security.access.method.P;
import org.springframework.security.access.prepost.PreAuthorize;
public class MyMethodSecurityService {
@PreAuthorize("#strValue == 'aaa' and #intValue == 1")
public String getMessage(@P("strValue") String strValue, @P("intValue") int intValue) {
return "strValue=" + strValue + ", intValue=" + intValue;
}
}
Une annotation appelée «@ P» est fournie.
Vous pouvez maintenant annoter le paramètre et spécifier le nom du paramètre avec value
pour obtenir le nom du paramètre via une annotation.
La classe d'implémentation est ʻAnnotationParameterNameDiscoverer`.
Disponible pour Java 8 et supérieur lorsqu'il est compilé avec l'option -parameters
au moment de la compilation.
La classe d'implémentation est StandardReflectionParameterNameDiscoverer
.
Pour utiliser cette fonction, il est nécessaire de générer des informations de débogage au moment de la compilation. Plus précisément, il est nécessaire de spécifier au moins «vars» avec l'option «-g».
Au fait, si vous compilez avec Gradle, cette option est activée par défaut, vous pouvez donc utiliser cette fonctionnalité sans vous en soucier.
La classe d'implémentation est LocalVariableTableParameterNameDiscoverer
.
Les fonctions ci-dessus sont appliquées dans l'ordre "Annotation" -> "Réflexion" -> "Analyse de fichier de classe", et le nom trouvé en premier est utilisé.
Recommended Posts