HttpSecurity 權限配置
主要是通過 HttpSecurity 配置訪問控制權限,它仍是繼承自 WebSecurityConfigurerAdapter ,重寫其中的 configure(HttpSecurity http) 方法, 沿用上面的 SecurityConfig 類:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 這是一個過期的方法
* 指明密碼不用加密
*/
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
/**
* 定義兩個用戶,並設置密碼和角色
* 從 Spring5.0 開始,密碼必須要加密
* 基於內存的用戶認證
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("123456")
.roles("admin")
.and()
.withUser("user1")
.password("123")
.roles("user");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 只有 admin 角色才能訪問路徑 /admin/**
.antMatchers("/admin/**").hasRole("admin")
// admin 和 user 角色都能訪問路徑 /user/**
.antMatchers("/user/**").hasAnyRole("admin", "user")
// 其他路徑請求,只要是登錄用戶都可以訪問
.anyRequest().authenticated()
.and()
// 配置表單登錄
.formLogin()
// 處理登錄的 URL
.loginProcessingUrl("/doLogin")
// 與登錄相關的請求都可以通過
.permitAll()
.and()
// 關閉 csrf 保護
.csrf().disable();
}
}
通過 http.authorizeRequests().antMatchers("路徑").hasRole("角色") ,賦予相應角色的路徑訪問權限。
HttpSecurity 登錄表單配置
仍然沿用上面的configure(HttpSecurity http)
方法。
登錄成功
在前后端分離的項目中,登錄成功后,后台向前台返回一個 json 字符串,表示登錄成功,具體配置如下:
// 登錄成功后的處理
.successHandler(new AuthenticationSuccessHandler() {
// authentication 保存了登錄成功的用戶信息
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
// 返回 json 格式的數據
httpServletResponse.setContentType("application/json;charset=utf-8");
PrintWriter writer = httpServletResponse.getWriter();
Map<String, Object> map = new HashMap<>(16);
map.put("status:", 200);
map.put("msg:",authentication.getPrincipal());
writer.write(new ObjectMapper().writeValueAsString(map));
writer.flush();
writer.close();
}
})
效果如下圖:
登錄失敗
登錄失敗后,后台仍向前台返回一個 json 字符串,並注明登錄失敗的原因。
登錄失敗后的具體配置如下:
//登錄失敗后的處理
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setContentType("application/json;charset=utf-8");
PrintWriter writer = httpServletResponse.getWriter();
Map<String, Object> map = new HashMap<>(16);
map.put("status:", 401);
if (e instanceof LockedException) {
map.put("msg:", "賬戶被鎖定,登錄失敗!");
}else if (e instanceof BadCredentialsException){
map.put("msg:", "用戶名或密碼輸入錯誤,登錄失敗");
}else if (e instanceof DisabledException){
map.put("msg:", "賬戶被禁用,登錄失敗!");
}else if (e instanceof AccountExpiredException){
map.put("msg:", "賬戶過期,登錄失敗!");
}else if (e instanceof CredentialsExpiredException){
map.put("msg:", "密碼過期,登錄失敗");
}else {
map.put("msg:","登錄失敗!");
}
writer.write(new ObjectMapper().writeValueAsString(map));
writer.flush();
writer.close();
}
})
效果如下:
對於登錄失敗后的各種情況,可以通過查看抽象類 AuthenticationException
的繼承關系,獲悉所有的異常情況:
注銷登錄
仍然沿用上面的configure(HttpSecurity http)
方法。
在 .permitAll()
方法后,配置注銷登錄的信息:
// 與登錄相關的請求都可以通過
.permitAll()
// 注銷登錄的配置
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
// 返回 json 格式的數據
httpServletResponse.setContentType("application/json;charset=utf-8");
PrintWriter writer = httpServletResponse.getWriter();
Map<String, Object> map = new HashMap<>(16);
map.put("status:", 200);
map.put("msg:","注銷登錄成功!");
writer.write(new ObjectMapper().writeValueAsString(map));
writer.flush();
writer.close();
}
})
注銷登錄是一個 get 請求,效果如下:
每天學習一點點,每天進步一點點。