Spring Security深入淺出--3、記住我實現和源碼分析以及實現圖片驗證碼功能

目錄

 

實現圖片驗證碼功能

代碼重構

記住我

記住我基本原理

代碼實現

 記住我源碼分析

登陸

服務重新啓動


項目地址:鏈接:https://pan.baidu.com/s/106lZU8P9gHG4A3aP4OpOgQ
提取碼:xs3v

實現圖片驗證碼功能

開發生成圖片驗證碼接口

用來封裝image圖片


public class ImageCode extends ValidateCode {
	
	private BufferedImage image; 
	
	public ImageCode(BufferedImage image, String code, int expireIn){
		super(code, expireIn);
		this.image = image;
	}
	
	public ImageCode(BufferedImage image, String code, LocalDateTime expireTime){
		super(code, expireTime);
		this.image = image;
	}
	
	public BufferedImage getImage() {
		return image;
	}

	public void setImage(BufferedImage image) {
		this.image = image;
	}

}

將生成的圖片放入到session裏面

生成圖形驗證碼

	/**
	 * 系統配置
	 */
	@Autowired
	private SecurityProperties securityProperties;
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.imooc.security.core.validate.code.ValidateCodeGenerator#generate(org.
	 * springframework.web.context.request.ServletWebRequest)
	 */
	@Override
	public ImageCode generate(ServletWebRequest request) {
		int width = ServletRequestUtils.getIntParameter(request.getRequest(), "width",
				securityProperties.getCode().getImage().getWidth());
		int height = ServletRequestUtils.getIntParameter(request.getRequest(), "height",
				securityProperties.getCode().getImage().getHeight());
		//生成圖片對象
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		//生成圖片對象



		Graphics g = image.getGraphics();


		//生成干擾條紋
		Random random = new Random();

		g.setColor(getRandColor(200, 250));
		g.fillRect(0, 0, width, height);
		g.setFont(new Font("Times New Roman", Font.ITALIC, 20));
		g.setColor(getRandColor(160, 200));
		for (int i = 0; i < 155; i++) {
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}
		//生成干擾條紋

		//生成四位隨機數
		String sRand = "";
		for (int i = 0; i < securityProperties.getCode().getImage().getLength(); i++) {  //securityProperties.getCode().getImage().getLength()  生成條形碼的長度
			String rand = String.valueOf(random.nextInt(10));
			sRand += rand;
			g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
			g.drawString(rand, 13 * i + 6, 16);
		}
		//生成四位隨機數


		g.dispose();

		return new ImageCode(image, sRand, securityProperties.getCode().getImage().getExpireIn());  //securityProperties.getCode().getImage().getExpireIn()過期時間
	}
	
	/**
	 * 生成隨機背景條紋
	 * 
	 * @param fc
	 * @param bc
	 * @return
	 */
	private Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255) {
			fc = 255;
		}
		if (bc > 255) {
			bc = 255;
		}
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}

	public SecurityProperties getSecurityProperties() {
	return securityProperties;
}

	public void setSecurityProperties(SecurityProperties securityProperties) {
		this.securityProperties = securityProperties;
	}

將該請求加入到安全配置裏面

啓動之後

當圖片驗證碼發送給security框架之後,我們需要手動寫security過濾器來處理圖形驗證碼

創建過濾類ValidateCodeFilter繼承OncePerRequestFilter(使得只過濾一次)

將自己寫的過濾器加入的security過濾器鏈中

運行

代碼重構

驗證碼基本參數可配置

首先配置core項目中的屬性ImageCodeProperties

創建ValidateCodeProperties來封裝各個屬性類型(後期還會有短信驗證)


 

進入到demo項目中寫應用級的配置

請求級的配置

core項目中的ValidateCodeController對象

 

啓動項目指揮,請求裏面的width會覆蓋配置裏面的width,配置裏面的width會覆蓋默認的width

 

驗證碼攔截的接口可配置

 將url進行統一處理

這樣的話,直接訪問user  user/*的路徑都會被攔截下來,並且返回報錯信息

驗證碼的生成邏輯可配置

 

其實ImageCodeGenerator類也可以 @component註解直接注入,但是通過配置類註解來來創建實現,這樣的話可以通過@ConditionalOnMissingBean進行判斷是否bean裏面已經存在一個相同的bean

如果在其他地方又注入了它的話,這個時候上面的imageCodeGenerator就會失效

記住我

記住我基本原理

瀏覽器發送認證請求給後臺,當UsernamePasswordAuthenticationFilter認證成功之後通過RemenberMeService將token信息保存到TokenRepositoty以及數據庫中,然後將token寫入到瀏覽器Cookie中;

當瀏覽器過了幾天再次發送服務請求的時候,直接被RemenberMeAuthenticationFilter攔截下來,讀取Cookie中的token,在調用RemeberMeService去數據庫查找Token,調用UserDetailsService完成認證。

RememberMeAuthenticationFilter過濾器一般都在自定義過濾器的末尾,當前面的認證都不可行的時候,就嘗試的調用它

代碼實現

創建persistentTokenRepository的bean,用來調用數據庫驗證使用的。tokenRepository.setCreateTableOnStartup(true)方法的目的是第一次初始化的時候,在數據庫創建對象的表來存放token。

配置過期時間

調用userDetailsService

 

總體邏輯就是調用persistenTokenRepository()方法,去數據庫去或者存放對應的token,設置過期時間,然後調用userDetailsService驗證加載用戶信息。

 記住我源碼分析

登陸

 進入到UsernamePasswordAuthenticationFilter類中

認證成功之後,進入到AbstractAuthenticationProcessingFilter方法中

 調用rememberMeServices

調用tokenRepository向數據庫添加新的token

addCookie()的方法就是將token寫到瀏覽器cookie裏面

 

服務重新啓動

判斷前面的認證是否認證成功,如果沒有認證成功就進入if語句

通過tokenSeries去數據庫拿token的值 ,然後就是做token的相關檢查

然後就是調用userDetailsService,去獲取用戶信息

 

 認證成功之後,將認證信息保存到session裏面

 

發佈了483 篇原創文章 · 獲贊 104 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章