写这篇文章是由于我作了一个电商网站项目,近期刚加上权限控制。整个过程很简单,在此给你们梳理一下,也算是本身对知识点的一个总结。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相反,若是没有交集便可