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、暴力手段,修改源码,前面说的修改默认filter只是修改配置文件以替换filter而已,这种是直接改了里面的源码,但是这种不符合OO设计原则,而且不实际,不可用。
本文主要介绍了关于spring security自定义认证登录的相关内容,分享出来供大家参考学习,下面话不多说了,一起来看看详细的介绍吧。
1.概要
1.1.简介
spring security是一种基于Spring AOP和Servlet过滤器的安全框架,以此来管理权限认证等。
1.2.spring security 自定义认证流程
1)认证过程
生成未认证的AuthenticationToken
↑(获取信息) (根据AuthenticationToken分配provider) AuthenticationFilter -> AuthenticationManager -> AuthenticationProvider ↓(认证) UserDetails(通常查询数据库获取) ↓(通过) 生成认证成功的AuthenticationToken ↓(存放) SecurityContextHolder
2)将AuthenticationFilter添加到security过滤链(资源服务器中配置),例如:
http.addFilterBefore(AuthenticationFilter, AbstractPreAuthenticatedProcessingFilter.class)
o:}
http.addFilterAfter(AuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
2.Ejemplo de inicio de sesión con短信a través de número de teléfono
2.1.Ambiente de desarrollo
2.2.Análisis de código central
2.2.1.Flujo de autenticación de inicio de sesión personalizado
2.2.1.1.Token de inicio de sesión de autenticación personalizado
/** * Token de inicio de sesión de teléfono móvil * * @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) { throw new IllegalArgumentException( "No se puede establecer este token como confiable - use constructor which takes a GrantedAuthority list instead"); } super.setAuthenticated(false); } @Override public Object getCredentials() { return null; } @Override public Object getPrincipal() { return this.principal; } @Override public void eraseCredentials() { super.eraseCredentials(); } }
Nota:
setAuthenticated():Determina si está autenticado
2.2.1.1.Filtro de autenticación personalizado
/** * Autenticador de inicio de sesión por 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 cargando ..."); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { throw new AuthenticationServiceException("Método de autenticación no soportado: " + request.getMethod()); } //obtener móvil String mobile = obtainMobile(request); //armar token MobileLoginAuthenticationToken authRequest = new MobileLoginAuthenticationToken(mobile); // Permitir que las subclases establezcan la propiedad "details" setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } /** * establecer detalles de autenticación */ private void setDetails(HttpServletRequest request, MobileLoginAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); } /** * Obtener el número de teléfono */ private String obtainMobile(HttpServletRequest request) { return request.getParameter(mobileParameterName); } public void setPostOnly(boolean postOnly) { this.postOnly = postOnly; } }
Nota:Método attemptAuthentication():
2.2.1.1.Proveedor de inicio de sesión de autenticación personalizado
/** * Proveedor de autenticación de inicio de sesión por SMS * * @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 ..."); } /** * Autenticación */ @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { //Obtener la información del token encapsulado por el filtro MobileLoginAuthenticationToken authenticationToken = (MobileLoginAuthenticationToken) authentication; //Obtener información del usuario (autenticación de base de datos) UserDetails userDetails = customUserDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); //no cumplido if (userDetails == null) { lanzar una InternalAuthenticationServiceException("No se puede obtener la información del usuario"); } //cumplido MobileLoginAuthenticationToken authenticationResult = new MobileLoginAuthenticationToken(userDetails, userDetails.getAuthorities()); authenticationResult.setDetails(authenticationToken.getDetails()); return authenticationResult; } /** * Según el tipo de token, determina qué proveedor usar */ @Override public boolean supports(Class<63;> authentication) { return MobileLoginAuthenticationToken.class.isAssignableFrom(authentication); } }
Nota:método authenticate()
2.2.1.1.configuración de autenticación de inicio de sesión personalizada
@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.autorizadorAutenticacion(mobileLoginAuthenticationProvider) .agregarFiltroDespues(mobileLoginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); } }
Nota:método configure()}
Instanciar AuthenticationFilter y AuthenticationProvider
Agregar AuthenticationFilter y AuthenticationProvider al Spring Security.
2.2.2.Verificación de código de verificación personalizado basado en redis
2.2.2.1.Filtro de código de verificación personalizado basado en redis
/** * Filtro de código de verificación * * @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; /** * Clase utilitaria para verificar si la URL de la solicitud coincide con la URL configurada */ 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(); if (pathMatcher.match(url, request.getRequestURI())) {}} String deviceId = request.getHeader("deviceId"); if (StringUtils.isBlank(deviceId)) { lanzar nueva ExcepcionPersonalizada(HttpStatus.NOT_ACCEPTABLE.value(), "No hay deviceId en la cabecera de la solicitud"); } String codeParamName = customYmlConfig.getLogins().getMobile().getParameter().getCode(); String code = request.getParameter(codeParamName); if (StringUtils.isBlank(code)) { lanzar nueva ExcepcionPersonalizada(HttpStatus.NOT_ACCEPTABLE.value(), "No hay código en los parámetros de la solicitud"); } String key = SystemConstant.DEFAULT_MOBILE_KEY_PIX + deviceId; SmsCodePO smsCodePo = (SmsCodePO) redisTemplate.opsForValue().get(key); if (smsCodePo.isExpried()){ lanzar nueva ExcepcionPersonalizada(HttpStatus.BAD_REQUEST.value(), "El código de verificación ha expirado"); } String smsCode = smsCodePo.getCode(); if (StringUtils.isBlank(smsCode)) { lanzar nueva ExcepcionPersonalizada(HttpStatus.BAD_REQUEST.value(), "El código de verificación no existe"); } if (StringUtils.equals(code, smsCode)) {}} redisTemplate.delete(key); //Dejalo ir filterChain.doFilter(request, response); } else { throw new CustomException(HttpStatus.BAD_REQUEST.value(), "El código de validación es incorrecto"); } } else { //Dejalo ir filterChain.doFilter(request, response); } } }
Nota:doFilterInternal()
Validación de filtro de código personalizado
2.2.2.2.Añadir el filtro de validación de código personalizado a la cadena de filtros de spring security
http.addFilterBefore(validateCodeFilter, AbstractPreAuthenticatedProcessingFilter.class)
Nota:Añadir antes del filtro de preautenticación
3.Efecto de prueba
Adjuntamos la dirección de la fuente del código a continuación:https://gitee.com/CatalpaFlat/springSecurity.git (Descarga local)
Resumen
Esto es todo el contenido de este artículo. Espero que el contenido de este artículo tenga un valor de referencia y aprendizaje para todos. Si tienes alguna pregunta, puedes dejar un comentario para comunicarnos. Gracias por tu apoyo a los tutoriales de clamor.
Declaración: El contenido de este artículo se obtiene de la red, y el derecho de autor pertenece al propietario original. El contenido es proporcionado por usuarios de Internet de manera autónoma y subido por ellos mismos. Este sitio no posee los derechos de propiedad, no ha sido editado por humanos y no asume ninguna responsabilidad legal. Si encuentra contenido sospechoso de copyright, por favor envíe un correo electrónico a: notice#oldtoolbag.com (al enviar un correo electrónico, reemplace # con @) para denunciar, y proporcione pruebas relacionadas. Una vez confirmado, este sitio eliminará inmediatamente el contenido sospechoso de infracción.