English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Catégorie d'utilisation de Spring Security :
Comment utiliser Spring Security, ceux qui ont cherché sur Baidu savent, il y a quatre méthodes en tout, de la plus simple à la plus complexe :
1, sans utiliser de base de données, toutes les données sont écrites dans le fichier de configuration, c'est aussi un exemple de demo dans le document officiel;
2, utiliser la base de données, concevoir la base de données en fonction du code source par défaut de Spring Security, c'est-à-dire que la base de données est déjà fixée, cette méthode n'est pas flexible et la conception de la base de données est très primitive, son utilité est mauvaise;
3, Spring Security et Acegi sont différents, il ne peut pas modifier le filtre par défaut, mais il supporte l'insertion de filtres, donc selon cela, nous pouvons insérer notre propre filtre pour une utilisation flexible;
4, méthodes de force brute, modification du code source, ce que nous avons dit de la modification du filtre par défaut consiste à remplacer le fichier de configuration pour le filtre, mais cela modifie directement le code source, ce qui n'est pas conforme aux principes de conception OO et n'est pas pratique.
Ce document présente principalement les informations sur la personnalisation de l'authentification de Spring Security, et est partagé pour que tout le monde puisse l'utiliser comme référence pour l'apprentissage. Il n'y a pas grand-chose à dire, regardons donc l'introduction détaillée.
1.Résumé
1.1.Introduction
Spring Security est un cadre de sécurité basé sur Spring AOP et Servlet Filter, utilisé pour gérer l'autorisation et l'authentification.
1.2.Procédure personnalisée de sécurité Spring
1) Processus d'authentification
Générer un AuthenticationToken non authentifié
↑(obtenir des informations) (allouer le provider en fonction de AuthenticationToken) AuthenticationFilter -> AuthenticationManager -> AuthenticationProvider ↓(authentification) UserDetails (généralement récupéré de la base de données) ↓(par) Générer un AuthenticationToken de succès d'authentification ↓(contient) SecurityContextHolder
2Ajouter AuthenticationFilter à la chaîne de filtrage de sécurité (configuré dans le serveur de ressources), par exemple :
http.addFilterBefore(AuthenticationFilter, AbstractPreAuthenticatedProcessingFilter.class)
ou :
http.addFilterAfter(AuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
2.Exemple de connexion par SMS avec le numéro de téléphone
2.1.Environnement de développement
2.2.Analyse du code principal
2.2.1.Procédure de connexion personnalisée
2.2.1.1.Token de connexion personnalisé
/** * Token de connexion mobile * * @author : CatalpaFlat */ public class MobileLoginAuthenticationToken extends AbstractAuthenticationToken { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private static final Logger logger = LoggerFactory.getLogger(MobileLoginAuthenticationToken.class.getName()); private final Object principal; public MobileLoginAuthenticationToken(String mobile) { super(null); this.principal = mobile; this.setAuthenticated(false); logger.info("MobileLoginAuthenticationToken setAuthenticated ->false loading ...); } public MobileLoginAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) { super(authorities); this.principal = principal; // must use super, as we override super.setAuthenticated(true); logger.info("MobileLoginAuthenticationToken setAuthenticated ->true loading ...); } @Override public void setAuthenticated(boolean authenticated) {}} if (authenticated) { lancer une new IllegalArgumentException( "Ce jeton ne peut pas être défini comme de confiance" - utilisez le constructeur qui prend une liste de GrantedAuthority au lieu de cela"); } super.setAuthenticated(false); } @Override public Object getCredentials() { return null; } @Override public Object getPrincipal() { return this.principal; } @Override public void eraseCredentials() { super.eraseCredentials(); } }
Remarque :
setAuthenticated() : juger si il est authentifié
2.2.1.1.Définir un filtre d'authentification personnalisé
/** * Filtre de connexion par SMS mobile * * @author : CatalpaFlat */ public class MobileLoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter { private boolean postOnly = true; private static final Logger logger = LoggerFactory.getLogger(MobileLoginAuthenticationFilter.class.getName()); @Getter @Setter private String mobileParameterName; public MobileLoginAuthenticationFilter(String mobileLoginUrl, String mobileParameterName, String httpMethod) {}} super(new AntPathRequestMatcher(mobileLoginUrl, httpMethod)); this.mobileParameterName = mobileParameterName; logger.info("MobileLoginAuthenticationFilter en cours de chargement ..."); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { lancer une nouvelle AuthenticationServiceException("Méthode d'authentification non prise en charge : ") + request.getMethod()); } //Obtenir le mobile String mobile = obtainMobile(request); //Assemblez le jeton MobileLoginAuthenticationToken authRequest = new MobileLoginAuthenticationToken(mobile); // Permettre aux sous-classes de définir la propriété "details" setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } /** * Définir les détails de l'authentification */ private void setDetails(HttpServletRequest request, MobileLoginAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); } /** * 获取手机号 */ private String obtainMobile(HttpServletRequest request) { return request.getParameter(mobileParameterName); } public void setPostOnly(boolean postOnly) { this.postOnly = postOnly; } }
Remarque :attemptAuthentication()方法:
2.2.1.1.自定义认证登录提供者
/** * 手机短信登录认证提供者 * * @author : CatalpaFlat */ public class MobileLoginAuthenticationProvider implements AuthenticationProvider { private static final Logger logger = LoggerFactory.getLogger(MobileLoginAuthenticationProvider.class.getName()); @Getter @Setter private UserDetailsService customUserDetailsService; public MobileLoginAuthenticationProvider() { logger.info("MobileLoginAuthenticationProvider loading ..."); } /** * 认证 */ @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { //Obtenir des informations sur le token encapsulé par le filtre MobileLoginAuthenticationToken authenticationToken = (MobileLoginAuthenticationToken) authentication; //获取用户信息(数据库认证) UserDetails userDetails = customUserDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); //Échec if (userDetails == null) { lancer une nouvelle InternalAuthenticationServiceException("Impossible d'obtenir des informations utilisateur"); } //Succès MobileLoginAuthenticationToken authenticationResult = new MobileLoginAuthenticationToken(userDetails, userDetails.getAuthorities()); authenticationResult.setDetails(authenticationToken.getDetails()); return authenticationResult; } /** * Selon le type de token, décidez quel fournisseur utiliser */ @Override public boolean supports(Class<63;> authentication) { return MobileLoginAuthenticationToken.class.isAssignableFrom(authentication); } }
Remarque :méthode authenticate()
2.2.1.1.Configuration personnalisée pour l'authentification de connexion mobile
@Configuration(SpringBeanNameConstant.DEFAULT_CUSTOM_MOBILE_LOGIN_AUTHENTICATION_SECURITY_CONFIG_BN) public class MobileLoginAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { private static final Logger logger = LoggerFactory.getLogger(MobileLoginAuthenticationSecurityConfig.class.getName()); @Value("${login.mobile.url}") private String defaultMobileLoginUrl; @Value("${login.mobile.parameter}") private String defaultMobileLoginParameter; @Value("${login.mobile.httpMethod}") private String defaultMobileLoginHttpMethod; @Autowired private CustomYmlConfig customYmlConfig; @Autowired private UserDetailsService customUserDetailsService; @Autowired private AuthenticationSuccessHandler customAuthenticationSuccessHandler; @Autowired private AuthenticationFailureHandler customAuthenticationFailureHandler; public MobileLoginAuthenticationSecurityConfig() { logger.info("MobileLoginAuthenticationSecurityConfig loading ..."); } @Override public void configure(HttpSecurity http) throws Exception { MobilePOJO mobile = customYmlConfig.getLogins().getMobile(); String url = mobile.getUrl(); String parameter = mobile.getParameter().getMobile(); String httpMethod = mobile.getHttpMethod(); MobileLoginAuthenticationFilter mobileLoginAuthenticationFilter = new MobileLoginAuthenticationFilter(StringUtils.isBlank(url) ? urlParDefautMobileLogin : url, StringUtils.isBlank(parametre) ? urlParDefautMobileLogin : parametre, StringUtils.isBlank(httpMethod) ? methodeHttpParDefautMobileLogin : httpMethod); mobileLoginAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); mobileLoginAuthenticationFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler); mobileLoginAuthenticationFilter.setAuthenticationFailureHandler(customAuthenticationFailureHandler); MobileLoginAuthenticationProvider mobileLoginAuthenticationProvider = new MobileLoginAuthenticationProvider(); mobileLoginAuthenticationProvider.setCustomUserDetailsService(customUserDetailsService); http.authenticationProvider(mobileLoginAuthenticationProvider) .ajouterFiltreApres(mobileLoginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); } }
Remarque :méthode configure()
Instancier AuthenticationFilter et AuthenticationProvider
Ajouter AuthenticationFilter et AuthenticationProvider au Spring Security.
2.2.2.Vérification de code personnalisé basé sur Redis
2.2.2.1.Filtre de validation de code personnalisé basé sur Redis
/** * Filtre de code de validation * * @author : CatalpaFlat */ @Component(SpringBeanNameConstant.DEFAULT_VALIDATE_CODE_FILTER_BN) public class ValidateCodeFilter extends OncePerRequestFilter implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(ValidateCodeFilter.class.getName()); @Autowired private CustomYmlConfig customYmlConfig; @Autowired private RedisTemplate<Object, Object> redisTemplate; /** * Classe utilitaire pour vérifier si l'URL de la requête correspond à l'URL configurée */ private AntPathMatcher pathMatcher = new AntPathMatcher(); public ValidateCodeFilter() { logger.info("Loading ValidateCodeFilter..."); } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String url = customYmlConfig.getLogins().getMobile().getUrl(); si (pathMatcher.match(url, request.getRequestURI())) {}} String deviceId = request.getHeader("deviceId"); si (StringUtils.isBlank(deviceId)) { lancer une nouvelle ExceptionCustome(HttpStatus.NOT_ACCEPTABLE.value(), "Pas de deviceId dans l'en-tête de la requête"); } String codeParamName = customYmlConfig.getLogins().getMobile().getParameter().getCode(); String code = request.getParameter(codeParamName); si (StringUtils.isBlank(code)) { lancer une nouvelle ExceptionCustome(HttpStatus.NOT_ACCEPTABLE.value(), "Pas de code dans les paramètres de la requête"); } String key = SystemConstant.DEFAULT_MOBILE_KEY_PIX + deviceId; SmsCodePO smsCodePo = (SmsCodePO) redisTemplate.opsForValue().get(key); si (smsCodePo.isExpried()){ lancer une nouvelle ExceptionCustome(HttpStatus.BAD_REQUEST.value(), "Le code de vérification a expiré"); } String smsCode = smsCodePo.getCode(); si (StringUtils.isBlank(smsCode)) { lancer une nouvelle ExceptionCustome(HttpStatus.BAD_REQUEST.value(), "Le code de vérification n'existe pas"); } if (StringUtils.equals(code, smsCode)) {}} redisTemplate.delete(key); //Laissez-le aller filterChain.doFilter(request, response); } Lancer une nouvelle CustomException(HttpStatus.BAD_REQUEST.value(), "Le code de validation est incorrect"); } } //Laissez-le aller filterChain.doFilter(request, response); } } }
Remarque :doFilterInternal()
Validation personnalisée du code de validation
2.2.2.2.Ajouter le filtre de validation personnalisé au chaînage des filtres de sécurité de Spring
http.addFilterBefore(validateCodeFilter, AbstractPreAuthenticatedProcessingFilter.class)
Remarque :Ajouter avant le filtre de prétraitement d'authentification
3.Test des effets
Voici l'adresse de la source :https://gitee.com/CatalpaFlat/springSecurity.git (Téléchargement local)
Résumé
Voici la totalité du contenu de cet article. J'espère que le contenu de cet article aura une certaine valeur de référence pour votre apprentissage ou travail. Si vous avez des doutes, vous pouvez laisser des messages pour échanger. Merci de votre soutien au tutoriel de cri.
Déclaration : Le contenu de cet article est extrait du réseau, propriété des auteurs originaux, contribué et téléversé par les utilisateurs d'Internet. Ce site n'est pas propriétaire des droits, n'a pas été édité par l'homme, et n'assume pas la responsabilité des responsabilités juridiques associées. Si vous trouvez du contenu présumé de violation de droits d'auteur, veuillez envoyer un e-mail à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour faire une plainte, et fournir des preuves pertinentes. Une fois vérifié, ce site supprimera immédiatement le contenu présumé de violation de droits d'auteur.