目錄
項目地址:鏈接: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()需要自己去定義,這樣也就可以實現代碼重用