English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Spring Security使用分类:
如何使用Spring Security,相信百度过的人都知道,总共有四种用法,从简单到复杂为:
1、不使用数据库,所有数据都写在配置文件中,这也是官方文档中的demo;
2、使用数据库,根据Spring Security默认实现代码设计数据库,也就是说数据库已经固定了,这种方法不够灵活,而且那个数据库设计得很简陋,实用性差;
3、Spring Security与Acegi不同,它不能修改默认filter了,但支持插入filter,因此我们可以插入自己的filter来灵活使用;
4. Mezzi violenti, modifica del codice sorgente, come sopra menzionato, la modifica del filtro di default è solo la sostituzione del file di configurazione del filtro, questo è un cambiamento diretto del codice interno, ma non è conforme ai principi di design OO e non è pratico, non utilizzabile.
Questo articolo introduce i contenuti relativi all'autenticazione di login personalizzata di spring security, condiviso per riferimento e studio. Non c'è molto da dire, vediamo insieme la descrizione dettagliata.
1. Sintesi
1.1. Introduzione
Spring security è una struttura di sicurezza basata su Spring AOP e filtri Servlet, utilizzata per gestire l'autenticazione e i permessi.
1.2. Flusso di autenticazione personalizzato di spring security
1) Procedura di autenticazione
Genera AuthenticationToken non autenticato
↑(ottenimento informazioni) (assegnazione provider in base a AuthenticationToken) AuthenticationFilter -> AuthenticationManager -> AuthenticationProvider ↓(autenticazione) UserDetails (solitamente ricercato nel database) ↓(attraverso) Genera AuthenticationToken di autenticazione riuscita ↓(albero) SecurityContextHolder
2) Aggiungi AuthenticationFilter alla catena di filtri di sicurezza (configurato nel server delle risorse), ad esempio:
http.addFilterBefore(AuthenticationFilter, AbstractPreAuthenticatedProcessingFilter.class)
o:
http.addFilterAfter(AuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
2. Esempio di login via SMS con numero di telefono
2.1. Ambiente di sviluppo
2.2. Analisi del codice di cuore
2.2.1. Flusso di autenticazione di login personalizzato
2.2.1.1. Token di login di autenticazione personalizzato
/** * Token di login per telefono * * @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 caricamento ..."); public MobileLoginAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) { super(authorities); this.principal = principal; // è necessario utilizzare super, poiché stiamo sovrascrivendo super.setAuthenticated(true); logger.info("MobileLoginAuthenticationToken setAuthenticated ->true caricamento ..."); @Override public void setAuthenticated(boolean authenticated) { if (authenticated) { throw new IllegalArgumentException; "Non è possibile impostare questo token come fidato - utilizzare il costruttore che accetta una lista di GrantedAuthority invece" super.setAuthenticated(false); @Override public Object getCredentials() { return null; @Override public Object getPrincipal() { return this.principal; @Override public void eraseCredentials() { super.eraseCredentials();
Nota:
setAuthenticated():giudicare se è autenticato
2.2.1.1. Filtri di autenticazione personalizzati per il login
/** * Filtri di login tramite SMS * * @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 caricamento in corso ... @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { throw new AuthenticationServiceException("Metodo di autenticazione non supportato: " + request.getMethod()); // Ottieni il numero di telefono String mobile = obtainMobile(request); // Assembla il token MobileLoginAuthenticationToken authRequest = new MobileLoginAuthenticationToken(mobile); // Permetti alle sottoclassi di impostare la proprietà "details" setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); /** * Imposta le informazioni dettagliate dell'autenticazione dell'identità */ private void setDetails(HttpServletRequest request, MobileLoginAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); /** * Ottieni il numero di telefono */ private String obtainMobile(HttpServletRequest request) { return request.getParameter(mobileParameterName); public void setPostOnly(boolean postOnly) { this.postOnly = postOnly;
Nota: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 { //获取过滤器封装的token信息 MobileLoginAuthenticationToken authenticationToken = (MobileLoginAuthenticationToken) authentication; //获取用户信息(数据库认证) UserDetails userDetails = customUserDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); // Negativo if (userDetails == null) { throw new InternalAuthenticationServiceException("Impossibile ottenere informazioni sull'utente"); // Positivo MobileLoginAuthenticationToken authenticationResult = new MobileLoginAuthenticationToken(userDetails, userDetails.getAuthorities()); authenticationResult.setDetails(authenticationToken.getDetails()); return authenticationResult; /** * Secondo il tipo di token, determinare quale Provider utilizzare */ @Override public boolean supports(Class<?> authentication) { return MobileLoginAuthenticationToken.class.isAssignableFrom(authentication);
Nota:metodo authenticate()
2.2.1.1. Customizzazione della configurazione di autenticazione di login
@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) ? defaultMobileLoginUrl : url, StringUtils.isBlank(parameter) ? defaultMobileLoginUrl : parameter, StringUtils.isBlank(httpMethod) ? defaultMobileLoginHttpMethod : httpMethod); mobileLoginAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); mobileLoginAuthenticationFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler); mobileLoginAuthenticationFilter.setAuthenticationFailureHandler(customAuthenticationFailureHandler); MobileLoginAuthenticationProvider mobileLoginAuthenticationProvider = new MobileLoginAuthenticationProvider(); mobileLoginAuthenticationProvider.setCustomUserDetailsService(customUserDetailsService); http.authenticationProvider(mobileLoginAuthenticationProvider) .aggiungiFiltroDopo(mobileLoginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
Nota:metodo configure()}
Instanzia AuthenticationFilter e AuthenticationProvider
Aggiungi AuthenticationFilter e AuthenticationProvider al framework di sicurezza Spring.
2.2.2. Verifica del codice di sicurezza personalizzata basata su Redis
2.2.2.1. Filtri di verifica del codice di sicurezza personalizzati basati su Redis
/** * Filtri di verifica del codice di sicurezza * * @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; /** * Strumento di utilità per verificare se l'URL della richiesta corrisponde all'URL configurato */ 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(); se (pathMatcher.match(url, request.getRequestURI())) {}} String deviceId = request.getHeader("deviceId"); se (StringUtils.isBlank(deviceId)) { lancia una nuova CustomException(HttpStatus.NOT_ACCEPTABLE.value(), "Non ci sono deviceId nell'intestazione della richiesta"); String codeParamName = customYmlConfig.getLogins().getMobile().getParameter().getCode(); String code = request.getParameter(codeParamName); se (StringUtils.isBlank(code)) { lancia una nuova CustomException(HttpStatus.NOT_ACCEPTABLE.value(), "Non ci sono codici nei parametri della richiesta"); String key = SystemConstant.DEFAULT_MOBILE_KEY_PIX + deviceId; SmsCodePO smsCodePo = (SmsCodePO) redisTemplate.opsForValue().get(key); se (smsCodePo.isExpried()){ lancia una nuova CustomException(HttpStatus.BAD_REQUEST.value(), "Il codice di verifica è scaduto"); String smsCode = smsCodePo.getCode(); se (StringUtils.isBlank(smsCode)) { lancia una nuova CustomException(HttpStatus.BAD_REQUEST.value(), "Il codice di verifica non esiste"); if (StringUtils.equals(code, smsCode)) { redisTemplate.delete(key); //Lascia che vada filterChain.doFilter(request, response); else { throw new CustomException(HttpStatus.BAD_REQUEST.value(), "Il codice di validazione è errato"); else { //Lascia che vada filterChain.doFilter(request, response);
Nota:doFilterInternal()
Verifica del filtro di verifica del codice personalizzato
2.2.2.2. Aggiungere il filtro di verifica del codice personalizzato alla catena dei filtri di spring security
http.addFilterBefore(validateCodeFilter, AbstractPreAuthenticatedProcessingFilter.class)
Nota:Aggiungere prima del filtro di pre-autenticazione
3. Effetti del test
Ecco l'indirizzo del codice sorgente:https://gitee.com/CatalpaFlat/springSecurity.git Download locale
Conclusione
Questo è tutto il contenuto dell'articolo, speriamo che il contenuto di questo articolo abbia un valore di riferimento per la tua apprendimento o lavoro. Se hai domande, puoi lasciare un messaggio per scambiare opinioni, grazie per il supporto della guida a urlo.
Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, il copyright è di proprietà del rispettivo autore, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non detiene i diritti di proprietà, non è stato editato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una email a: notice#oldtoolbag.com (al momento dell'invio dell'email, sostituisci # con @) per segnalare, fornendo prove pertinenti. Una volta verificata, questo sito eliminerà immediatamente il contenuto sospetto di violazione del copyright.