English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Категории использования Spring Security:
Как использовать Spring Security, я уверен, что кто-то, кто искал в Бaidu, знает, всего существует四种 способов использования, от простого к сложному:;
1. Не использовать базу данных, все данные пишутся в файл конфигурации, это также демонстрация в официальной документации;
2. Использование базы данных, проектирование базы данных на основе стандартного кода реализации Spring Security, то есть база данных уже фиксирована, этот метод не гибок и дизайн базы данных очень примитивен, его практичность низка;
3. Spring Security и Acegi различаются, так как он не позволяет изменять mặc định filter, но поддерживает вставку filter, поэтому на основе этого мы можем вставить свой filter для использования гибкого;
4. Враждебные методы, модификация исходного кода, как было сказано ранее, модификация défaut filter - это только замена файла конфигурации для замены фильтра, это直接 модифицирует исходный код, но это не соответствует принципам ОО-дизайна и не является практичным и неэффективным.
Эта статья подробно рассказывает о пользовательской аутентификации входа Spring security и предоставляет информацию для参考 и обучения. Не будем тратить время на лишние слова, давайте перейдем к детальному рассмотрению.
1.Краткое описание
1.1.Обзор
Spring security - это безопасность на основе Spring AOP и Servlet фильтров, которая используется для управления аутентификацией и разрешениями.
1.2.Пользовательский процесс аутентификации Spring security
1) Процесс аутентификации
Создание токена аутентификации с неуспешным результатом
↑ (получение информации) (распределение provider по токену аутентификации) AuthenticationFilter -> AuthenticationManager -> AuthenticationProvider ↓ (аутентификация) UserDetails (обычно извлекается из базы данных) ↓ (через) Создание токена аутентификации с успешным результатом ↓ (хранение) SecurityContextHolder
2) Добавьте AuthenticationFilter в цепочку фильтров безопасности (настройте на ресурсном сервере), например:
http.addFilterBefore(AuthenticationFilter, AbstractPreAuthenticatedProcessingFilter.class)
или:
http.addFilterAfter(AuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
2.Пример входа через SMS с использованием номера телефона
2.1.Рабочая среда
2.2.Анализ ядра кода
2.2.1.Процесс аутентификации входа с помощью пользовательского токена
2.2.1.1.Пользовательский токен для аутентификации входа
/** * Токен для手机登录 * * @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; "Не можно установить этот токен в доверенный - используйте конструктор, который принимает список GrantedAuthority"); } super.setAuthenticated(false); } @Override public Object getCredentials() { return null; } @Override public Object getPrincipal() { return this.principal; } @Override public void eraseCredentials() { super.eraseCredentials(); } }
Примечание:
setAuthenticated(): determine if authenticated
2.2.1.1. Custom authentication login filter
/** * SMS login filter * * @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 загрузка ... } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { throw new AuthenticationServiceException("Метод аутентификации не поддерживается: " + request.getMethod()); } // Получить номер телефона String mobile = obtainMobile(request); // Собрать токен MobileLoginAuthenticationToken authRequest = new MobileLoginAuthenticationToken(mobile); // Разрешить подклассам устанавливать свойства "details" setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } /** * Установка подробной информации для的身份认证 */ 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; } }
Примечание: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()); // Не успешно if (userDetails == null) { throw new InternalAuthenticationServiceException("Unable to obtain user information"); } // Успешно MobileLoginAuthenticationToken authenticationResult = new MobileLoginAuthenticationToken(userDetails, userDetails.getAuthorities()); authenticationResult.setDetails(authenticationToken.getDetails()); return authenticationResult; } /** * Определите,哪个 Провайдер использовать, в зависимости от типа токена */ @Override public boolean supports(Class<?> authentication) { return MobileLoginAuthenticationToken.class.isAssignableFrom(authentication); } }
Примечание:метод authenticate()
2.2.1.1. Настройка пользовательской конфигурации аутентификации登录а
@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.авторизацияПоставщик(mobileLoginAuthenticationProvider) .добавитьФильтрПосле(mobileLoginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); } }
Примечание:метод configure()
Инсталлировать AuthenticationFilter и AuthenticationProvider
Добавить AuthenticationFilter и AuthenticationProvider в Spring Security.
2.2.2. Настройка проверки кода безопасности на основе Redis
2.2.2.1. Настройка фильтра проверки кода безопасности на основе Redis
/** * Фильтр проверки кода безопасности * * @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; /** * Инструмент класса для проверки соответствия запрашиваемого URL URL, настроенному в конфигурации */ 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)) { throw new CustomException(HttpStatus.NOT_ACCEPTABLE.value(), "deviceId не найден в заголовке запроса"); } String codeParamName = customYmlConfig.getLogins().getMobile().getParameter().getCode(); String code = request.getParameter(codeParamName); if (StringUtils.isBlank(code)) { throw new CustomException(HttpStatus.NOT_ACCEPTABLE.value(), "Код не найден в параметрах запроса"); } String key = SystemConstant.DEFAULT_MOBILE_KEY_PIX + deviceId; SmsCodePO smsCodePo = (SmsCodePO) redisTemplate.opsForValue().get(key); if (smsCodePo.isExpried()){ throw new CustomException(HttpStatus.BAD_REQUEST.value(), "Код проверки истек"); } String smsCode = smsCodePo.getCode(); if (StringUtils.isBlank(smsCode)) { throw new CustomException(HttpStatus.BAD_REQUEST.value(), "Код проверки не существует"); } if (StringUtils.equals(code, smsCode)) { redisTemplate.delete(key); //let it go filterChain.doFilter(request, response); } throw new CustomException(HttpStatus.BAD_REQUEST.value(), "Validation code is incorrect"); } } //let it go filterChain.doFilter(request, response); } } }
Примечание:doFilterInternal()
Пользовательская проверка кода проверки
2.2.2.2. Добавить пользовательский фильтр проверки кода в цепочку фильтров spring security
http.addFilterBefore(validateCodeFilter, AbstractPreAuthenticatedProcessingFilter.class)
Примечание:Добавить в фильтр предварительной аутентификации
3. Результат тестирования
В конце прилагается адрес исходного кода:https://gitee.com/CatalpaFlat/springSecurity.git (Локальная загрузка)
Обобщение
Вот и все, что есть в этой статье, надеюсь, что содержимое статьи будет иметь определенную образовательную или профессиональную ценность для вас. Если у вас есть вопросы, пожалуйста, оставляйте комментарии для обсуждения, спасибо за поддержку呐喊 руководства.
Заявление: содержимое этой статьи взято из Интернета, авторские права принадлежат соответствующему владельцу. Контент был предложен пользователями Интернета и загружен самостоятельно. Этот сайт не обладает правами собственности, не производил редактирование вручную и не несет ответственности за соответствующие юридические обязательства. Если вы обнаружите подозрительное нарушение авторских прав, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (во время отправки письма, пожалуйста, замените # на @) для сообщения о нарушении и предоставьте соответствующие доказательства. При подтверждении факта нарушения сайт незамедлительно удалят涉嫌侵权的内容。