先說一下AuthConfig.java Spring Security的主要配置文件之一 AuthConfig
1 @Configuration 2 @EnableWebSecurity 3 public class AuthConfig extends WebSecurityConfigurerAdapter { 4 @Override 5 protected void configure(HttpSecurity httpSecurity) throws Exception { 6 httpSecurity.authorizeRequests() 7 .antMatchers("/css/**","/staic/**", "/js/**","/images/**").permitAll() 8 .antMatchers("/", "/login","/session_expired").permitAll() 9 .and() 10 .formLogin() 11 .loginPage("/login") 12 .defaultSuccessUrl("/main_menu") 13 .failureUrl("/loginError") 14 .usernameParameter("txtUserCd") 15 .passwordParameter("txtUserPwd") 16 .permitAll() 17 .and() 18 .logout() 19 .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) 20 .logoutSuccessUrl("/") 21 .deleteCookies("JSESSIONID") 22 .invalidateHttpSession(true) 23 .permitAll() 24 .and() 25 .sessionManagement() 26 .invalidSessionUrl("/session_expired") 27 .maximumSessions(1) 28 .maxSessionsPreventsLogin(true) 29 .expiredUrl("/session_expired"); 30 httpSecurity.logout().permitAll(); 31 32 } 33 34 @Autowired 35 AuthUserService authUserService; 36 public void globalAuthConfig(AuthenticationManagerBuilder auth) throws Exception { 37 auth.userDetailsService(authUserService); 38 //auth.inMemoryAuthentication().withUser("user").password("password"); 39 } 40 /*@Configuration 41 protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter { 42 @Autowired 43 AuthUserService authUserService; 44 45 @Override 46 public void init(AuthenticationManagerBuilder auth) throws Exception { 47 //auth.inMemoryAuthentication().withUser("user").password("password"); 48 auth.userDetailsService(authUserService); 49 } 50 }*/ 51 }
一、configur方法 基本配置
No | Source | Comment |
L1 | @Configuration | 這個就是java形式的bean spring3.0以后 允許以 @Configuration 注解來代替XML形式的bean |
L2 | @EnableWebSecurity | 用這個注解開啟 spring security配置驗證開啟 |
L3 | WebSecurityConfigurerAdapter | 這個需要我們繼承WebSecurityConfigurerAdapter適配器且重寫 configure 函數 來實現訪問的控制(那些訪問/資源 需要哪些權限)和登錄的驗證(數據庫驗證/內存驗證) |
L6 | authorizeRequests() | 通過authorizeRequests()配下的子函來完成訪問/授權 配置 |
L7,8 | antMatchers/permitAll | antMatchers里配置的資源是可以被所有用戶訪問(permitAll)的 |
L9 | and() | 類似於結束標簽 |
L10 | formLogin | 通過formLogin()配下的函數對登錄form進行配置 |
L11 | loginPage | 設置登錄頁面 |
L12 | defaultSuccessUrl | 默認登錄成功跳轉地址 |
L13 | failureUrl | 默認登錄失敗跳轉地址 |
L14,15 | usernameParameter passwordParameter |
用戶名密碼驗證用 *這里的參數要和畫面上控件名保持一致 |
L18 | logout() | 通過logout()配下的函數對注銷進行配置 |
L19 | .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) | 設置注銷用的請求URL |
L20 | logoutSuccessUrl | 設置注銷成功后的跳轉URL |
L21 | deleteCookies | 消除Cookie |
L22 | invalidateHttpSession | 銷毀Session |
L25 | sessionManagement | 通過sessionManagement配下的函數對session配置 |
L27 | maximumSessions | 同一用戶session上限設定 *比如同一個用戶 多次登錄 |
L28 | maxSessionsPreventsLogin | maximumSessions設定的上限啟用 * 超出報錯 |
L29 | expiredUrl | 超過session上限跳轉URL設定 |
二、globalAuthConfig方法 認證
先說L38 這行注掉的 是內存認證模式 意思是創建了一個 名為user 密碼 為password的用戶
然后是 L37 這也是認證核心
先看一下這個 傳入參數的的構成 也就是 AuthUserService 類
1 @Service 2 public class AuthUserService implements UserDetailsService{ 3 4 @Autowired 5 MstUsersMapper mstUsersMapper; 6 7 @Override 8 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 9 Users users =mstUsersMapper.selectByPrimaryKey(username); 10 if(users == null) { 11 throw new UsernameNotFoundException("User not found for name:"+username); 12 } 13 return new AuthUser(users); 14 } 15 16 public String getAuthorityByLoginId(String loginId ){ 17 //Map<String,String> authKindMap = new HashMap<String,String>(); 18 String auth = mstUsersMapper.selectAuthorityByLoginId(loginId); 19 return auth; 20 } 21 }
可以看到我們是 實現了UserDetailsService 然后重寫了一個loadUserByUsername和追加了一個 getAuthorityByLoginId函數
關於 getAuthorityByLoginId 好說的基本上就是 當前用戶的權限
然后是loadUserByUsername
可以通過名字基本上可以看的出是 通過name 取user 的信息 實際上也是這樣 這里並不判斷你輸的密碼對不對 主要是
判斷你輸入的用戶名在數據庫里存不存在 不存在 報錯 扔出 存在 實例化一個 AuthUser 返回
這個AuthUser 類也很重要 實現了UserDetails 如下
1 public class AuthUser implements UserDetails { 2 private static final long serialVersionUID = 1L; 3 4 private String userId; 5 private String loginId; 6 private String password; 7 private String authorityKind; 8 public AuthUser(Users users) { 9 super(); 10 this.userId = users.getUserId(); 11 this.loginId = users.getLoginId(); 12 this.password = users.getPassword(); 13 this.authorityKind = users.getAuthorityKind(); 14 } 15 16 @Override 17 public Collection<GrantedAuthority> getAuthorities() { 18 List<GrantedAuthority> list = new ArrayList<GrantedAuthority>(); 19 list.add(new SimpleGrantedAuthority(authorityKind)); 20 return list; 21 } 22 23 @Override 24 public String getPassword() { 25 return password; 26 } 27 28 @Override 29 public String getUsername() { 30 return loginId; 31 } 32 33 @Override 34 public boolean isAccountNonExpired() { 35 return true; 36 } 37 38 @Override 39 public boolean isAccountNonLocked() { 40 return true; 41 } 42 43 @Override 44 public boolean isCredentialsNonExpired() { 45 return true; 46 } 47 48 @Override 49 public boolean isEnabled() { 50 return true; 51 }
這里的幾個點要注意一下
L17 getAuthorities 它返回了一個權限集合 這個集合是和你在畫面側用的hasAnyAuthority('ROLE_USER','ROLE_ADMIN') 這個函數相呼應的
換言之你之所以能在畫面側如上那樣寫也是因為你在這里吧把當前用戶的權限set進去了
然后看一下我們實現的 UserDetails這個父類,如下官網文檔給的信息.
No | Modifier and Type | Method and Description |
---|---|---|
1 |
java.util.Collection<? extends GrantedAuthority> |
getAuthorities()
Returns the authorities granted to the user.
|
2 |
java.lang.String |
getPassword()
Returns the password used to authenticate the user.
|
3 |
java.lang.String |
getUsername()
Returns the username used to authenticate the user.
|
4 |
boolean |
isAccountNonExpired()
Indicates whether the user's account has expired.
|
5 |
boolean |
isAccountNonLocked()
Indicates whether the user is locked or unlocked.
|
6 |
boolean |
isCredentialsNonExpired()
Indicates whether the user's credentials (password) has expired.
|
7 |
boolean |
isEnabled()
Indicates whether the user is enabled or disabled.
|
前3個應該不用說了,從第四個開始說一下
isAccountNonExpired():當前賬號是否已經過期
isAccountNonLocked():當前賬號是否被鎖
isCredentialsNonExpired():當前賬號證書(密碼)是否過期
isEnabled():當前賬號是否被禁用
都要給設成true 否則登錄會報出來
還有實現一個UserDetailsService類如下
1 @Service 2 public class AuthUserService implements UserDetailsService{ 3 4 @Autowired 5 MstUsersMapper mstUsersMapper; 6 7 @Override 8 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 9 Users users =mstUsersMapper.selectByPrimaryKey(username); 10 if(users == null) { 11 throw new UsernameNotFoundException("User not found for name:"+username); 12 } 13 return new AuthUser(users); 14 } 15 16 public String getAuthorityByLoginId(String loginId ){ 17 //Map<String,String> authKindMap = new HashMap<String,String>(); 18 String auth = mstUsersMapper.selectAuthorityByLoginId(loginId); 19 return auth; 20 } 21 }
如你看到那樣loadUserByUsername這函數並不做密碼驗證只是拿username取用戶信息,當然取不到報錯
取到交給AuthUser,然后spring boot 自己再去判斷密碼,以及前面說的那個幾個check
剩下的就是 Controller這個就沒有特別要說的到git上看代碼就完了
最后貼一下執行效果圖及git地址
(完)