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)
oder:
http.addFilterAfter(AuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
2.以手机号短信登录为例
2.1.开发环境
2.2.核心代码分析
2.2.1.自定义登录认证流程
2.2.1.1.自定义认证登录Token
/** * 手机登录Token * * @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( "Dieser Token kann nicht als vertrauenswürdig gesetzt werden - verwende den Konstruktor, der eine Liste von GrantedAuthority annimmt"); } super.setAuthenticated(false); } @Override public Object getCredentials() { return null; } @Override public Object getPrincipal() { return this.principal; } @Override public void eraseCredentials() { super.eraseCredentials(); } }
Anmerkung:
setAuthenticated():Prüft, ob berechtigt
2.2.1.1.benutzerdefinierter Authentifizierungs-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 wird geladen ..."); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { throw new AuthenticationServiceException("Authentication method not supported: "); + request.getMethod()); } //Mobile erhalten String mobile = obtainMobile(request); //Token zusammenstellen MobileLoginAuthenticationToken authRequest = new MobileLoginAuthenticationToken(mobile); // Ermöglicht Unterklassen, die "details"-Eigenschaft zu setzen setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } /** * Legt die Details der Identitätsauthentifizierung fest */ 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; } }
Anmerkung: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 { //Erhalten Sie die Token-Informationen, die vom Filter verpackt wurden MobileLoginAuthenticationToken authenticationToken = (MobileLoginAuthenticationToken) authentication; //获取用户信息(数据库认证) UserDetails userDetails = customUserDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); //Nicht erfolgreich if (userDetails == null) { throw new InternalAuthenticationServiceException("Es ist nicht möglich, Benutzerinformationen zu erhalten"); } //Erfolgreich MobileLoginAuthenticationToken authenticationResult = new MobileLoginAuthenticationToken(userDetails, userDetails.getAuthorities()); authenticationResult.setDetails(authenticationToken.getDetails()); return authenticationResult; } /** * Nach dem Typ des Tokens wird bestimmt, welchen Provider man verwenden soll */ @Override public boolean supports(Class<63;> authentication) { return MobileLoginAuthenticationToken.class.isAssignableFrom(authentication); } }
Anmerkung:authenticate() - Methode
2.2.1.1.eigenständige Authentifizierungs- und Anmeldekonfiguration
@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) .addFilterAfter(mobileLoginAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); } }
Anmerkung:configure() Methode
Instanziieren Sie AuthenticationFilter und AuthenticationProvider
Fügen Sie AuthenticationFilter und AuthenticationProvider zu Spring Security hinzu.
2.2.2.Benutzerdefinierter Prüfcode-Prüfer basierend auf Redis
2.2.2.1.Benutzerdefinierter Prüfcode-Filter basierend auf Redis
/** * Prüfcode-Filter * * @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; /** * Klasse zum Überprüfen, ob die Anfrage-URL mit der konfigurierten URL übereinstimmt */ 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(), "Not deviceId in the head of the request"); } String codeParamName = customYmlConfig.getLogins().getMobile().getParameter().getCode(); String code = request.getParameter(codeParamName); if (StringUtils.isBlank(code)) { throw new CustomException(HttpStatus.NOT_ACCEPTABLE.value(), "Not code in the parameters of the request"); } 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(), "The verification code has expired"); } String smsCode = smsCodePo.getCode(); if (StringUtils.isBlank(smsCode)) { throw new CustomException(HttpStatus.BAD_REQUEST.value(), "Verification code does not exist"); } if (StringUtils.equals(code, smsCode)) {}} redisTemplate.delete(key); //Lassen Sie es gehen filterChain.doFilter(request, response); } else { throw new CustomException(HttpStatus.BAD_REQUEST.value(), "Der Validierungscodes ist falsch"); } } else { //Lassen Sie es gehen filterChain.doFilter(request, response); } } }
Anmerkung:doFilterInternal()
Benutzerdefinierte Validierungscode-Überprüfung
2.2.2.2.Fügen Sie den benutzerdefinierten Validierungscode-Filter zur Spring Security-Filterkette hinzu
http.addFilterBefore(validateCodeFilter, AbstractPreAuthenticatedProcessingFilter.class)
Anmerkung:Fügen Sie es vor der Authentifizierungs-Präprozessierungsfilter hinzufügen
3.Testeffekt
Am Ende finden Sie die Adresse der Quelldatei:https://gitee.com/CatalpaFlat/springSecurity.git (Lokaler Download)
Zusammenfassung
Das ist der gesamte Inhalt dieses Artikels. Wir hoffen, dass der Inhalt dieses Artikels für Ihre Lern- oder Arbeitsaktivitäten einen gewissen Referenzwert hat. Wenn Sie Fragen haben, können Sie gerne Kommentare hinterlassen. Vielen Dank für Ihre Unterstützung für das呐喊教程.
Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet übernommen und gehört dem Urheberrechtsinhaber. Der Inhalt wurde von Internetbenutzern freiwillig beigesteuert und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Verantwortlichkeiten. Wenn Sie urheberrechtlich relevante Inhalte entdecken, freuen wir uns über eine E-Mail an: notice#oldtoolbag.com (Bitte ersetzen Sie # durch @, wenn Sie eine Meldung senden, und fügen Sie relevante Beweise bei. Sobald nachgewiesen, wird diese Website die beanstandeten urheberrechtlichen Inhalte sofort löschen.)