Spring Security深入淺出--1、基於restful的基本實現

目錄

一、Spring Security基本原理

二、security的簡單實現

三、個性化認證流程

自定義登陸界面

自定義登陸成功和失敗處理


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

一、Spring Security基本原理

簡單來說Spring Security就是一個過濾器鏈,對於藍色的過濾器我們可以修改和添加,其他顏色的過濾器鏈是默認的無法修改

斷點驗證

具體停留就不截圖了,在訪問的時候,例如請求路徑是/user,首先它進入的是FilterSecurityInterceptor,驗證發現沒有填寫用戶信息和名字,就會拋出異常被ExceptionTranslationFilter捕獲進入到beforeInvocation()方法中

接着前臺就會進入到登陸界面,輸入用戶和密碼,點擊登陸之後它會向後臺發送/login的請求並且進入到

UsernamePasswordAuthenticationFilter類中進行驗證用戶和密碼。驗證完畢之後進入到try方法

執行我們requestmapping

最後將信息返回給前臺

二、security的簡單實現

創建MyUserDetailsService類繼承UserDetailsService

@Component
public class MyUserDetailsService implements UserDetailsService, SocialUserDetailsService {

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private PasswordEncoder passwordEncoder;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.core.userdetails.UserDetailsService#
	 * loadUserByUsername(java.lang.String)
	 */
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		logger.info("表單登錄用戶名:" + username);
		return buildUser(username);
	}

	@Override
	public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException {
		logger.info("設計登錄用戶Id:" + userId);
		return buildUser(userId);
	}

	private SocialUserDetails buildUser(String userId) {
		// 根據用戶名查找用戶信息
		//根據查找到的用戶信息判斷用戶是否被凍結
                //“123456”是在數據庫中查詢到的密碼
		String password = passwordEncoder.encode("123456");
		logger.info("數據庫密碼是:"+password);
		return new SocialUser(userId, password,
				true, true, true, true,
				AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
	}

}

AuthorityUtils.commaSeparatedStringToAuthorityList("admin"):數據庫查出來並且傳入的是多個權限角色

對於SocialUser()中四個boolean值得說明,SocialUser是User類的實現,如果爲true,isEnabled()賬號未被刪除,isAccountNonExpired()賬號沒有過期,isAccountNonLocked()賬號沒有被鎖,isCredentialsNonExpired()身份認證沒有過期

PasswordEncoder接口中,encode方法是在你從數據庫中查到未加密的密碼對其進行加密,matches()方法是Security底層自動調用來對比輸入的密碼是否與數據庫的一致

三、個性化認證流程

自定義登陸界面

我們要處理的是如何解決當前端發送過來的是restful請求的時候返回的是狀態碼和json數據,當請求的是html頁面的時候,返回的是HTML頁面。

判斷授權形式

自定義登陸成功和失敗處理

由於前後端分離的原因,登陸成功和登陸失敗處理返回的不是html頁面而是json數據,所以我們得自定義登陸成功和失敗處理

@Component("imoocAuthenticationSuccessHandler")
public class ImoocAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private SecurityProperties securityProperties;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.web.authentication.
	 * AuthenticationSuccessHandler#onAuthenticationSuccess(javax.servlet.http.
	 * HttpServletRequest, javax.servlet.http.HttpServletResponse,
	 * org.springframework.security.core.Authentication)
	 */
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {

		logger.info("登錄成功");

		if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginType())) {  //如果登陸類型要求返回json就執行以下操作,否則執行else返回html
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter().write(objectMapper.writeValueAsString(authentication));
		} else {
			super.onAuthenticationSuccess(request, response, authentication);
		}

	}

}
@Component("imoocAuthenctiationFailureHandler")
public class ImoocAuthenctiationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private ObjectMapper objectMapper;
	
	@Autowired
	private SecurityProperties securityProperties;

	
	/* (non-Javadoc)
	 * @see org.springframework.security.web.authentication.AuthenticationFailureHandler#onAuthenticationFailure(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.AuthenticationException)
	 */
	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {
		
		logger.info("登錄失敗");
		
		if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginType())) {
			response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(exception.getMessage())));
		}else{
			super.onAuthenticationFailure(request, response, exception);
		}
		
		
	}

}

說明:對於securityProperties.getBrowser().getLoginType()需要自己去定義,這樣也就可以實現代碼重用

 

 

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