首頁  >  文章  >  資料庫  >  SpringSecurity+Redis認證過程是怎樣的

SpringSecurity+Redis認證過程是怎樣的

王林
王林轉載
2023-06-03 15:22:20969瀏覽

前言引入

當今市面上用於權限管理的流行的技術堆疊組合是

  • ssm shrio

  • SpringCloud SpringBoot SpringSecurity

SpringSecurity+Redis認證過程是怎樣的

這種搭配自然有其搭配的特點,由於SpringBoot的自動注入配置原理,在創建專案時就自動注入管理SpringSecurity的過濾器容器(DelegatingFilterProxy),而這個過濾器是整個SpringSercurity的核心。掌握著SpringSercurity整個權限認證過程,而SpringBoot很香的幫你將其自動注入了,而用ssm
去整合Security,將會耗用大量的配置文件,不易於開發,而Security的微服務權限方案,更是能和Cloud完美融合,於是Security比Shrio更強大,功能更齊全。

Security的核心設定檔

核心:Class SecurityConfig extends WebSecurityConfigurerAdapter

##繼承了WebSecurityConfigurerAdapter後我們專注於configure方法對於在整個安全認證的過程進行相關的配置,當然在配置之前我們先簡單了解一下流程

簡單的看了整個權限認證的流程,很輕易的總結得出,SpringSecurity核心的就是以下幾種配置項目了

  • 攔截器(Interceptor)

  • #過濾器(Filter)

  • 處理器(Handler,異常處理器,登入成功處理器)

那我們就先透過設定來完成認證過程吧! ! ! !

Security的認證流程

假設我們要實作一下的認證功能

1. 是登入請求

  • 我們需要先判斷驗證碼是否正確(驗證碼過濾器,透過addFilerbefore實現前置攔截)

  • #再判斷用戶名密碼是否正確(使用自帶的用戶名密碼過濾器,

    UsernamePasswordAuthenticationFilter

  • 設定異常處理器(Handler)透過IO流將例外訊息寫出

關於密碼校驗的流程:

UsernamePasswordAuthenticationFilter的密碼校驗規則是基於AuthenticationManagerBuilder(認證管理器)下的UserDetailsS​​ervice裡的規則進行驗證的:
其中的核心方法:

1.public

UserDetails *loadUserByUsername(String username)透過請求參數的使用者名稱去資料庫查詢是否存在,存在則將其封裝在UserDetails裡面,而驗證過程是透過AuthenticationManagerBuilder取得到UserDetail裡的username和password來校驗的,
這樣我們就可以透過

  • 設定yaml檔案設定帳號密碼

  • 透過資料庫結合UserDetail來設定帳號密碼

(UserDetailsS​​ervice中的方法,注意需要將UserDetailsS​​ervice注入AuthenticationManagerBuilder中)

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		SysUser sysUser = sysUserService.getByUsername(username);
		if (sysUser == null) {
			throw new UsernameNotFoundException("用户名或密码不正确");
		}
		// 注意匹配参数,前者是明文后者是暗纹
		System.out.println("是否正确"+bCryptPasswordEncoder.matches("111111",sysUser.getPassword()));
		return new AccountUser(sysUser.getId(), sysUser.getUsername(), sysUser.getPassword(), getUserAuthority(sysUser.getId()));
	}

通過了這個驗證後,過濾器放行,不通過就用自定義或預設的處理器處理

核心設定檔:

package com.markerhub.config;

import com.markerhub.security.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	LoginFailureHandler loginFailureHandler;

	@Autowired
	LoginSuccessHandler loginSuccessHandler;

	@Autowired
	CaptchaFilter captchaFilter;

	@Autowired
	JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

	@Autowired
	JwtAccessDeniedHandler jwtAccessDeniedHandler;

	@Autowired
	UserDetailServiceImpl userDetailService;

	@Autowired
	JwtLogoutSuccessHandler jwtLogoutSuccessHandler;

	@Bean
	JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
		JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
		return jwtAuthenticationFilter;
	}

	@Bean
	BCryptPasswordEncoder bCryptPasswordEncoder() {
		return new BCryptPasswordEncoder();
	}

	private static final String[] URL_WHITELIST = {

			"/login",
			"/logout",
			"/captcha",
			"/favicon.ico",

	};


	protected void configure(HttpSecurity http) throws Exception {

		http.cors().and().csrf().disable()

				// 登录配置
				.formLogin()
				.successHandler(loginSuccessHandler)
				.failureHandler(loginFailureHandler)

				.and()
				.logout()
				.logoutSuccessHandler(jwtLogoutSuccessHandler)

				// 禁用session
				.and()
				.sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.STATELESS)

				// 配置拦截规则
				.and()
				.authorizeRequests()
				.antMatchers(URL_WHITELIST).permitAll()
				.anyRequest().authenticated()

				// 异常处理器
				.and()
				.exceptionHandling()
				.authenticationEntryPoint(jwtAuthenticationEntryPoint)
				.accessDeniedHandler(jwtAccessDeniedHandler)

				// 配置自定义的过滤器
				.and()
				.addFilter(jwtAuthenticationFilter())
				.addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)

		;

	}

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailService);
	}
}

2. 不是登入請求

  • 透過JFilter來查看是否為登入狀態

使用Redis整合時的注意事項

#本質上還是寫篩選器鏈:

    ##在登入請求前新增篩選器
  • 注意驗證碼儲存在redis的失效時間,如果超過失效時間將會被驗證碼攔截器攔截下來
  • 需要準備一個產生驗證碼的接口,儲存在Redis中
  • 使用完驗證碼需要將其刪除
  • // 校验验证码逻辑
    	private void validate(HttpServletRequest httpServletRequest) {
    
    		String code = httpServletRequest.getParameter("code");
    		String key = httpServletRequest.getParameter("token");
    
    		if (StringUtils.isBlank(code) || StringUtils.isBlank(key)) {
    			System.out.println("验证码校验失败2");
    			throw new CaptchaException("验证码错误");
    		}
    
    		System.out.println("验证码:"+redisUtil.hget(Const.CAPTCHA_KEY, key));
    		if (!code.equals(redisUtil.hget(Const.CAPTCHA_KEY, key))) {
    			System.out.println("验证码校验失败3");
    			throw new CaptchaException("验证码错误");
    		}
    
    		// 一次性使用
    		redisUtil.hdel(Const.CAPTCHA_KEY, key);
    	}

以上是SpringSecurity+Redis認證過程是怎樣的的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除