配置步驟:
1.pom

<dependencies> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency>
2.配置WebSecurityConfigurerAdapter,SpringSecurty核心配置文件

package tools.perkinelmer.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import tools.perkinelmer.security.CustomUserService; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean UserDetailsService customUserService(){ //注冊UserDetailsService 的bean return new CustomUserService(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserService()); //user Details Service驗證 } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() //任何請求,登錄后可以訪問 .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/main") .failureUrl("/login?error") .permitAll() //登錄頁面用戶任意訪問 .and() .headers().frameOptions().disable() .and() .logout().permitAll(); //注銷行為任意訪問 } @Override public void configure(WebSecurity web) throws Exception { //解決靜態資源被攔截的問題 web.ignoring().antMatchers("/**/*.js", "/**/*.css", "/**/*.jpg", "/**/*.png"); } }
3.配置MVC,主要作用添加登錄頁面,主頁面,頁面映射,從而達到通過配置文件配置就能使thymeleaf從后台出來,內部應用起作用

package tools.perkinelmer.Config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Created by sang on 2017/1/10. */ @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login/login"); registry.addViewController("/main").setViewName("main/main"); } }
4.配置用戶,角色,並將權限交給SpringSceurity來處理
sysRole:

package tools.perkinelmer.entity; public class SysRole { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

package tools.perkinelmer.entity; import java.util.List; public class SysUser { private Integer id; private String username; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public List<SysRole> getRoles() { return roles; } public void setRoles(List<SysRole> roles) { this.roles = roles; } private String password; private List<SysRole> roles; }
自定義UserDetailsService讓權限控制交給springSecrity

package tools.perkinelmer.security; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import tools.perkinelmer.Mapper.UserMapper; import tools.perkinelmer.entity.SysRole; import tools.perkinelmer.entity.SysUser; /** * 用於將用戶權限交給 springsecurity 進行管控 * @author wangj01052 * */ public class CustomUserService implements UserDetailsService{ @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { SysUser user = userMapper.findByUserName(username); if(user == null){ throw new UsernameNotFoundException("用戶名不存在"); } List<SimpleGrantedAuthority> authorities = new ArrayList<>(); //用於添加用戶的權限。只要把用戶權限添加到authorities 就萬事大吉。 for(SysRole role:user.getRoles()) { authorities.add(new SimpleGrantedAuthority(role.getName())); System.out.println(role.getName()); } return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities); } }
5.寫好配置文件指定的登錄頁面,如果不指定的話springSecurty有自己默認的,登錄成功后寫好指定的主頁,這里都需要用thymeleaf模板來做,這樣權限控制可以有
sec:authorize="hasRole('ROLE_ADMIN')"來控制哪些元素顯示與否,用戶是否有權限訪問
權限名稱需要是ROLE_開頭的
6.springSercity配置需要注意點
1.首先當我們要自定義Spring Security的時候我們需要繼承自WebSecurityConfigurerAdapter來完成,相關配置重寫對應 方法即可。
2.我們在這里注冊CustomUserService的Bean,然后通過重寫configure方法添加我們自定義的認證方式。
3.在configure(HttpSecurity http)方法中,我們設置了登錄頁面,而且登錄頁面任何人都可以訪問,然后設置了登錄失敗地址,也設置了注銷請求,注銷請求也是任何人都可以訪問的。
4.permitAll表示該請求任何人都可以訪問,.anyRequest().authenticated()
,表示其他的請求都必須要有權限認證。
5.這里我們可以通過匹配器來匹配路徑,比如antMatchers方法,假設我要管理員才可以訪問admin文件夾下的內容,我可以這樣來寫:.antMatchers("/admin/**").hasRole("ROLE_ADMIN")
,也可以設置admin文件夾下的文件可以有多個角色來訪問,寫法如下:.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER")
6.可以通過hasIpAddress來指定某一個ip可以訪問該資源,假設只允許訪問ip為210.210.210.210的請求獲取admin下的資源,寫法如下.antMatchers("/admin/**").hasIpAddress("210.210.210.210")
7.更多的權限控制方式參看下表:
1.SpringSecurity運行機制
1)被認證請求被FilterSecurityInterceptor攔截看有沒有對應權限,如果沒有拋異常給ExceptionTranslationFilter 2)ExceptionTranslationFilter緩存原請求,利用LoginUrlAuthenticationEntryPoint入口跳轉到登錄界面 3)用戶在登錄界面填寫登錄信息后,提交,經過UsernamePasswordAuthenticationFilter對填寫的信息和從數據源中獲取的信息進行對比,成功則授權權限,並通過登錄成功后入口SavedRequestAwareAuthenticationSuccessHandler跳轉回原請求頁面(跳轉時有從緩存中對請求信息的恢復) 4)登錄完成后返回原請求,由FilterSecurityInterceptor進行權限的驗證(大部分工作有AbstractSecurityInterceptor來做),根據登錄成功后生成的Authentication(Authentication authentication = SecurityContextHolder.getContext().getAuthentication();由SecurityContextHolder持有,而其中的SecurityContext由SecurityContextPersistentFilter保存到session中從而實現request共享)中的權限和請求所需的權限對比,如果一致則成功執行,如果權限不正確則返回403錯誤碼 5)以上均是默認情況下,沒有經過配置的執行過程,當然可以自定義LoginUrlAuthenticationEntryPoint和SavedRequestAwareAuthenticationSuccessHandler實現根據不同的請求所需權限跳轉到不同登錄頁面及授權成功后根據權限跳轉到不同頁面,以及返回403錯誤碼時跳轉到對應的頁面(AccessDeniedHandlerImpl)在下一篇中會對其進行實現
2.根據這個機制我們可以做的事
1)自定義LoginUrlAuthenticationEntryPoint實現跳轉到不同登錄頁,如用戶訂單請求跳轉到用戶登錄頁,管理中心請求跳轉到管理員登錄頁 2)自定義SavedRequestAwareAuthenticationSuccessHandler實現直接點擊登錄成功后跳轉到指定的頁,如用戶登錄后跳轉到首頁,管理員登陸后跳轉到管理中心 3)通過AccessDeniedHandlerImpl處理雖讓登錄成功確沒有訪問權限的問題 4)自定義SimpleUrlAuthenticationFailureHandler來實現登錄失敗的情況,主要是用戶不存在或密碼錯誤問題。這種情況下能夠實現從哪個登錄頁面過來的還是返回原登錄頁,並攜帶錯誤信息
5)SimpleUrlAuthenticationSuccessHandler
3.thymeleaf,這個模板使用必須是通過后台獲得內部組件才能與java代碼融合起作用,這里我們需要注意的地方是需要通過后台訪問的頁面都要 用WebMvcConfigurerAdapter配置下
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login/login"); registry.addViewController("/main").setViewName("main/main"); } }
4.角色權限控制
springsecurity的角色權限控制,可通過配置角色組來作為角色,原來的角色作為權限,之后這個權限選項就可以作為控制頁面元素顯示,指定url訪問的控制元素

package tools.perkinelmer.security; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import tools.perkinelmer.Mapper.UserMapper; import tools.perkinelmer.entity.SysAuthority; import tools.perkinelmer.entity.SysRole; import tools.perkinelmer.entity.SysUser; /** * 用於將用戶權限交給 springsecurity 進行管控 * @author wangj01052 * */ public class CustomUserService implements UserDetailsService{ @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { SysUser user = userMapper.findByUserName(username); if(user == null){ throw new UsernameNotFoundException("用戶名不存在"); } List<SimpleGrantedAuthority> authorities = new ArrayList<>(); //用於添加用戶的權限。只要把用戶權限添加到authorities 就萬事大吉。 for(SysRole role:user.getRoles()) { List<SysAuthority> authoritys = role.getAuthoritys(); for(SysAuthority authority:authoritys){ authorities.add(new SimpleGrantedAuthority("ROLE_"+authority.getAuthority_id().toString())); } } return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities); } }