寫這篇文章是由於我作了一個電商網站項目,近期剛加上權限控制。整個過程很簡單,在此給你們梳理一下,也算是本身對知識點的一個總結。html
1、需求分析:
咱們都知道,電商網站在權限這一塊,有兩大塊內容:前端
一、用戶未登陸,部分頁面拒絕訪問(如:下訂單)java
二、不一樣角色用戶登陸看到的功能模塊不同(如:買家、賣家、客服等)mysql
基於以上需求,接下來咱們要解決的就是對用戶登陸的攔截以及對權限和角色的控制。web
2、項目環境說明:
使用SSM(SpringMVC+Spring+Mybatis)框架,mysql數據庫、maven項目管理工具,freemaker前端引擎。對以上又不懂的朋友們能夠本身去百度瞭解,這裏就廢話很少說了。spring
3、前期儲備知識(若是對Spring Security很熟悉的能夠跳過此步)
Security框架能夠精確控制頁面的一個按鈕、連接,它在頁面上權限的控制其實是經過它提供的標籤來作到的。sql
一個可以爲基於Spring的企業應用系統提供聲明式的安全訪問控制解決方式的安全框架(簡單說是對訪問權限進行控制嘛),應用的安全性包括用戶認證(Authentication)和用戶受權(Authorization)兩個部分。用戶認證指的是驗證某個用戶是否爲系統中的合法主體,也就是說用戶可否訪問該系統。用戶認證通常要求用戶提供用戶名和密碼。系統經過校驗用戶名和密碼來完成認證過程。用戶受權指的是驗證某個用戶是否有權限執行某個操做。在一個系統中,不一樣用戶所具備的權限是不一樣的。好比對一個文件來講,有的用戶只能進行讀取,而有的用戶能夠進行修改。通常來講,系統會爲不一樣的用戶分配不一樣的角色,而每一個角色則對應一系列的權限。spring security的主要核心功能爲認證和受權,全部的架構(如:Shiro安全框架)也是基於這兩個核心功能去實現的。數據庫
衆所周知 想要對對Web資源進行保護,最好的辦法莫過於Filter,要想對方法調用進行保護,最好的辦法莫過於AOP。因此springSecurity在咱們進行用戶認證以及授予權限的時候,經過各類各樣的攔截器來控制權限的訪問,從而實現安全。api
以下爲其主要過濾器 :安全
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
LogoutFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
UsernamePasswordAuthenticationFilter
BasicAuthenticationFilter
SecurityContextHolder:提供對SecurityContext的訪問
SecurityContext,:持有Authentication對象和其餘可能須要的信息
AuthenticationManager 其中能夠包含多個AuthenticationProvider
ProviderManager對象爲AuthenticationManager接口的實現類
AuthenticationProvider 主要用來進行認證操做的類 調用其中的authenticate()方法去進行認證操做
Authentication:Spring Security方式的認證主體
GrantedAuthority:對認證主題的應用層面的受權,含當前用戶的權限信息,一般使用角色表示
UserDetails:構建Authentication對象必須的信息,能夠自定義,可能須要訪問DB獲得
UserDetailsService:經過username構建UserDetails對象,經過loadUserByUsername根據userName獲取UserDetail對象
以上知識點來源於博客:springSecurity安全框架的學習和原理解讀
4、開始實戰:
本文內容主要實現三部份內容:
一、控制不一樣角色只能訪問網站中不一樣連接(與2做區分)
二、控制不一樣角色用戶看到網站中不一樣的模塊
三、對有權限控制的路徑,控制用戶session過時時從新跳轉到登陸頁面
- 在pom.xml文件中加入Security 座標:
-
<!--spring security 依賴包-->
-
-
<groupId>org.springframework.security</groupId>
-
<artifactId>spring-security-core</artifactId>
-
<version>
3.2.0.RELEASE</version>
-
-
-
<groupId>org.springframework.security</groupId>
-
<artifactId>spring-security-web</artifactId>
-
<version>
3.2.0.RELEASE</version>
-
-
-
<groupId>org.springframework.security</groupId>
-
<artifactId>spring-security-config</artifactId>
-
<version>
3.2.0.RELEASE</version>
-
-
-
<groupId>org.springframework.security</groupId>
-
<artifactId>spring-security-taglibs</artifactId>
-
<version>
3.2.0.RELEASE</version>
-
-
-
-
-
<filter-name>springSecurityFilterChain</filter-name>
-
-
org.springframework.web.filter.DelegatingFilterProxy
-
-
-
<!--mapping就是filter的映射,就是哪些文件用到這個filter-->
-
-
<filter-name>springSecurityFilterChain</filter-name>
-
<url-pattern>/*</url-pattern>
-
- Controller文件代碼 (SecurityConfig.java)
-
-
-
-
public class SecurityConfig extends WebSecurityConfigurerAdapter {
-
-
-
private UserDetailService userDetailService;
-
-
-
protected void configure(HttpSecurity http) throws Exception{
-
-
.antMatchers(
"/index/show").hasAnyRole("ADMIN","BUYER","SELLER")
-
.antMatchers(
"/cart/show").hasAnyRole("ADMIN","MAIJIA","SELLER")
-
-
.anyRequest().authenticated()
-
-
-
.loginPage(
"/index/login").permitAll()
-
.loginProcessingUrl(
"/j_spring_security_check")
-
.usernameParameter(
"j_username")
-
.passwordParameter(
"j_password")
-
.failureUrl(
"/index/login?error=true")
-
.defaultSuccessUrl(
"/index/show")
-
.and().logout().logoutUrl(
"/j_spring_security_logout").permitAll().logoutSuccessUrl("/index/login?logout=true")
-
-
.addFilter(myUsernamePasswordAuthenticationFilter)
-
-
.tokenValiditySeconds(
604800)
-
-
-
-
-
-
public void configure(WebSecurity web) throws Exception{
-
-
-
-
-
public void configure(AuthenticationManagerBuilder auth) throws Exception{
-
auth.userDetailsService(userDetailService);
-
-
-
-
public AuthenticationManager authenticationManagerBean() throws Exception {
-
return super.authenticationManagerBean();
-
-
- 接下來是Service層的代碼(UserDetailService.java)
-
-
public class UserDetailService implements UserDetailsService {
-
-
-
private UserDetailsDao userDetailsDao;
-
-
-
-
-
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
-
-
-
Users users = userDetailsDao.getUserByName(username);
-
-
-
throw new UsernameNotFoundException("找不到該帳戶信息!");
-
-
-
List<GrantedAuthority> list =
new ArrayList<GrantedAuthority>();
-
list.add(
new SimpleGrantedAuthority("ROLE_"+users.getRoles()));
-
-
User auth_user =
new User(users.getUsername(), users.getPassword(), list);
-
-
-
-
-
-
- 前端代碼 .ftl文件(在此只粘出一部分代碼,只顯示一下用法)
在ftl文件頭部加上,引入Security文件
<#assign sec=JspTaglibs["http://www.springframework.org/security/tags"]/>
-
<#--沒有登陸時 能看到買家、賣家全部信息-->
-
<
@sec.authorize ifNotGranted="ROLE_ADMIN,ROLE_MAIJIA,ROLE_SELLER,ROLE_BOTHSM">
-
-
<dt><a href=
"/jt/success/orderlist?page=1&orderPeriod=threemonth&orderType=allorder">買家中心</a></dt>
-
-
<a href=
"/jt/success/orderlist?page=1&orderPeriod=threemonth&orderType=allorder">所有訂單</a>
-
<a href=
"#">優惠券</a> <br />
-
<a href=
"/jt/cart/show" class="shoppingCart">個人購物車</a>
-
<a href=
"/jt/favorite/myfavorites/1/time">個人收藏</a>
-
-
-
-
-
<dt><a href=
"/jt/sellercenter/allproduct?page=1&fenleiId=allproduct">賣家中心</a> </dt>
-
-
<a href=
"/jt/seller/soldprolist?page=1&orderPeriod=threemonth&orderType=allorder">已賣出貨品</a>
-
<a href=
"/jt/release/release1">發佈供應產品</a><br />
-
<a href=
"/jt/sellercenter/allproduct?page=1&fenleiId=allproduct">管理供應產品</a>
-
<a href=
"/jt/news/toNewsReleaseListSeller?currentPage=1&newsStatus=2">發佈公告</a>
-
-
-
-
-
<#--登錄後,買家中心 只有以買家身份登陸能夠看到-->
-
<
@sec.authorize ifAnyGranted="ROLE_MAIJIA">
-
-
<dt><a href=
"/jt/success/orderlist?page=1&orderPeriod=threemonth&orderType=allorder">買家中心</a></dt>
-
-
<a href=
"/jt/success/orderlist?page=1&orderPeriod=threemonth&orderType=allorder">所有訂單</a>
-
<a href=
"#">優惠券</a> <br />
-
<a href=
"/jt/cart/show" class="shoppingCart">個人購物車</a>
-
<a href=
"/jt/favorite/myfavorites/1/time">個人收藏</a>
-
-
-
-
-
<#--登錄後,賣家中心 只有以賣家身份登陸能夠看到-->
-
<
@sec.authorize ifAnyGranted="ROLE_SELLER">
-
-
<dt><a href=
"/lbt/sellercenter/allproduct?page=1&fenleiId=allproduct">賣家中心</a> </dt>
-
-
<a href=
"/lbt/seller/soldprolist?page=1&orderPeriod=threemonth&orderType=allorder">已賣出貨品</a>
-
<a href=
"/lbt/release/release1">發佈供應產品</a><br />
-
<a href=
"/lbt/sellercenter/allproduct?page=1&fenleiId=allproduct">管理供應產品</a>
-
<a href=
"/lbt/news/toNewsReleaseListSeller?currentPage=1&newsStatus=2">發佈公告</a>
-
-
-
5、附加知識點:
頁面標籤的使用與權限配置相對應
authorize標籤判斷順序是: access->url->ifNotGranted->ifAllGranted->ifAnyGranted
但他們的關係是「與」: 即只要其中任何一個屬性不知足則該標籤中間的內容將不會顯示給用戶,舉個例子:
<sec:authorize ifAllGranted=」ROLE_ADMIN,ROLE_MEMBER」 ifNotGranted=」ROLE_SUPER」>知足纔會顯示給用戶 </sec:authorize>
標籤中間的內容只有在當前用戶擁有ADMIN,MEMBER角色,但不擁有SUPER權限時纔會顯示!
access屬性是基於角色判斷,url屬性是基於訪問路徑判斷。
對於ifAllGranted ,ifNotGranted,ifAnyGranted屬性的理解能夠與集合api類比
Collection grantedAuths :當前用戶擁有的權限
Collection requiredAuths : 當前要求的權限,即ifAllGranted ,ifNotGranted,ifAnyGranted 屬性的值
知足ifAllGranted: 只須要grantedAuths.containsAll(requiredAuths);返回true便可知足ifAnyGranted: 只須要grantedAuths.retainAll(requiredAuths);有內容便可(兩集合有交集)知足ifNotGranted:與Any相反,若是沒有交集便可