English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
正文
spring security使用分類:
1如何使用spring security,相信百度過的都知道,總共有四種用法,從簡到深為:
2、不用數據庫,全部數據寫在配置文件,這也是官方文檔裡面的demo;
3、使用數據庫,根據spring security默認實現代碼設計數據庫,也就是說數據庫已經固定了,這種方法不靈活,而且那個數據庫設計得很簡陋,實用性差;
4、spring security和Acegi不同,它不能修改默認filter了,但支持插入filter,所以根據這個,我們可以插入自己的filter來靈活使用;
、暴力手段,修改源碼,前面說的修改默認filter只是修改配置文件以替換filter而已,這種是直接改了里面的源碼,但是這種不符合OO設計原則,而且不實際,不可用。
1本文主要介紹了關於spring security自定義認證登錄的有關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。
1.1.概要
.簡介
1.2.spring security 自定義認證流程
1)認證過程
生成未認證的AuthenticationToken
↑(獲取信息) (根據AuthenticationToken分配provider) AuthenticationFilter -> AuthenticationManager -> AuthenticationProvider ↓(認證) UserDetails(一般查詢數據庫獲取) ↓(通過) 生成認證成功的AuthenticationToken ↓(存放) SecurityContextHolder
2)將AuthenticationFilter加入至security過濾鏈(資源服務器中配置),如:
http.addFilterBefore(AuthenticationFilter, AbstractPreAuthenticatedProcessingFilter.class)
또는:}
http.addFilterAfter(AuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
2.휴대폰 번호 문자 인증 예제로
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():인증 여부�断정
2.2.1.1.사용자 정의 인증 로그인 필터
/** * 휴대폰 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 로딩 중... "); } @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); //tokken을 조립합니다 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("사용자 정보를 가져올 수 없음"); } //통과 MobileLoginAuthenticationToken authenticationResult = new MobileLoginAuthenticationToken(userDetails, userDetails.getAuthorities()); authenticationResult.setDetails(authenticationToken.getDetails()); return authenticationResult; } /** * token 타입에 따라 사용할 Provider를 판단 */ @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 모바일로그인인증필터 = new MobileLoginAuthenticationFilter(StringUtils.isBlank(url) ? defaultMobileLoginUrl : url, StringUtils.isBlank(parameter) ? defaultMobileLoginUrl : parameter, StringUtils.isBlank(httpMethod) ? defaultMobileLoginHttpMethod : httpMethod); 모바일로그인인증필터.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); 모바일로그인인증필터.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler); 모바일로그인인증필터.setAuthenticationFailureHandler(customAuthenticationFailureHandler); MobileLoginAuthenticationProvider 모바일로그인인증공급자 = new MobileLoginAuthenticationProvider(); 모바일로그인인증공급자.setCustomUserDetailsService(customUserDetailsService); http.authenticationProvider(모바일로그인인증공급자) .addFilterAfter(모바일로그인인증필터, 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(), \ } 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.사용자 정의��인 코드 필터를 스프링 시큐리티 필터 체인에 추가
http.addFilterBefore(validateCodeFilter, AbstractPreAuthenticatedProcessingFilter.class)
주의:인증 предобработка фильтр에 추가하기 전에
3.테스트 효과
마지막으로 소스 코드 주소를 추가합니다:https://gitee.com/CatalpaFlat/springSecurity.git (로컬 다운로드)
정리
이것이 이 문서의 모든 내용입니다. 이 문서의 내용이 여러분의 학습이나 업무에 도움이 되길 바랍니다. 문제가 있으면 댓글을 달아 주시고, 감사합니다.呐喊 가이드에 대한 여러분의 지지에 감사합니다.
선언: 본 문서의 내용은 인터넷에서 가져왔으며, 저작권은 원작자에게 있으며, 인터넷 사용자가 자발적으로 기여하고 업로드한 내용으로, 본 사이트는 소유권을 가지지 않으며, 인공 편집을 거치지 않았으며, 관련 법적 책임도 부담하지 않습니다. 저작권 문제가 있는 내용을 발견하면 notice#w로 이메일을 보내 주시기 바랍니다.3codebox.com에 (이메일을 보내는 경우, #을 @으로 변경하십시오) 신고하시고 관련 증거를 제공하시면, 해당 내용이 사실로 확인되면 즉시 해당 내용을 삭제하겠습니다.