2019独角兽企业重金招聘Python工程师标准>>>

1.Spring Security介绍 

一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。

用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。

用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限 。

在认识Spring Security之前,所有的权限验证逻辑都混杂在业务逻辑中,用户的每个操作以前可能都需要对用户是否有进行该项操作的权限进行判断,来达到认证授权的 目的。类似这样的权限验证逻辑代码被分散在系统的许多地方,难以维护。AOP(Aspect Oriented Programming)和Spring Security为我们的应用程序很好的解决了此类问题,正如系统日志,事务管理等这些系统级的服务一样,我们应该将它作为系统一个单独的“切面”进行管 理,以达到业务逻辑与系统级的服务真正分离的目的,Spring Security将系统的安全逻辑从业务中分离出来。且对于上面提到的两种应用情景,Spring Security 框架都有很好的支持。在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。

spring security是为基于Spring的应用程序提供声明式安全保护的安全性框架。spring security提供了完整的安全性的解决方案,它能够在web请求级别和方法调用级别处理身份验证和授权。

2.使用Spring Security       

  ‍ 2.1 Spring Security3.0包含8个模块,我们应用程序至少要包含核心和配置这两个模块

模块 描述
ACL 支持通过访问控制列表为域对象提供安全性
CAS客户端 提供与JA-SIG的中心认证服务进行集成的功能
配置 包含了对Spring Security XML命令空间的支持
核心 提供了Spring Security基本库
LDAP 支持基于轻量目录访问协议进行认证
OpenID 支持分散式OpenID标准
Tag Library 包含了一组JSP标签来实现视图级别的安全性
Web 提供了Spring security基于过滤器的web安全性支持

  2.2使用 Spring Security配置命名空间

       好处:使用命令空间可以将安全性配置从成百行的xml减少到10行。因为很多东西都给你做了。

方法一:

<beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xmlns:security="http://www.springframework.org/schema/security"  xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  http://www.springframework.org/schema/security   http://www.springframework.org/schema/security/spring-security-3.0.xsd">  <!--  Spring-Security 的配置 -->  <!-- 注意开启use-expressions.表示开启表达式.  see:http://www.family168.com/tutorial/springsecurity3/html/el-access.html  -->  <security:http auto-config="true" use-expressions="true" access-denied-page="/auth/denied" >  <security:intercept-url pattern="/auth/login" access="permitAll"/>  <security:intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/>  <security:intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/>  <security:form-login  login-page="/auth/login"   authentication-failure-url="/auth/login?error=true"   default-target-url="/main/common"/>  <security:logout   invalidate-session="true"   logout-success-url="/auth/login"   logout-url="/auth/logout"/>  </security:http>  <!-- 指定一个自定义的authentication-manager :customUserDetailsService -->  <security:authentication-manager>  <security:authentication-provider user-service-ref="userServiceImpl">  <!--  <security:password-encoder ref="passwordEncoder"/>   --></security:authentication-provider>  </security:authentication-manager>
</beans>

           注意在这个配置文件里面不能扫包,就是如下语句

<context:component-scan base-package="com.kedacom.platform.security.service">
</context:component-scan>

方法二:将安全性的命令空间作为默认的命名空间

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context   http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">  <!--  Spring-Security 的配置 -->  <!--之前就是这个一直没有扫进来,所以创建bean有错误  注意有些可能不带支持这个扫包,就把头给换成现在这个可以扫包的  --><context:component-scan base-package="com.kedacom.service">
</context:component-scan><!-- 注意开启use-expressions.表示开启表达式.  see:http://www.family168.com/tutorial/springsecurity3/html/el-access.html  -->      <!-- auot-config表示会把那7个过滤器的关系自动弄好    access-denied-page 表示没有权限发送这个url--><http auto-config="true" use-expressions="true" access-denied-page="/auth/denied" >  <intercept-url pattern="/auth/login" access="permitAll"/>  <intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/>  <intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/>  <!-- 一般我们不提供登录页面,他自己会提供登录页面,所有我们要指定自己的登录页面,就在login-page里面指定其访问的url --><!-- authentication-failure-url 表示失败之后去的页面 --><!--  default-target-url  表示成功之后去的页面-->  <form-login  login-page="/auth/login"   authentication-failure-url="/auth/login?error=true"   default-target-url="/main/common"/>  <!--logout-success-url 表示退出成功之后去的页面  --><!--表示退出要发的url  -->      <logout   invalidate-session="true"   logout-success-url="/auth/login"   logout-url="/auth/logout"/>  </http>  <!-- 指定一个自定义的authentication-manager :customUserDetailsService -->  <authentication-manager>  <authentication-provider user-service-ref="userServiceImpl">  <!--  <security:password-encoder ref="passwordEncoder"/>   --></authentication-provider>  </authentication-manager>
</beans:beans>

这种命令空间,就可以避免为每种元素添加那令人讨厌的 "security: " 前缀了,且还可以扫包,免得要去注册自己实现的那个类的bean

 2.3基于内存用户存储进行认证管理

2.3.1  实例1,spring security的最简单的helloworld程序,用配置文件,将用户、权限、资源(url)硬编码在xml文件中,最简单的spring security的例子来讲解spring security怎么使用‍‍

环境:spring mvc3.2.5  ,maven3.2.1,spring security3.1

1>新建maven项目,加入如下依赖的jar包‍‍

对应的pom.xml文件内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.kedacom.webmvc</groupId><artifactId>securityfirstdemo</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>securityfirstdemo Maven Webapp</name><url>http://maven.apache.org</url><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><!-- 将jsp编译成servlet,没有的话,jsp会报错 --><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency><!--spring security安全框架 , 进行登录验证和授权验证的jar包 --><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId><version>${spring.security.version}</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-taglibs</artifactId><version>${spring.security.version}</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.0.3</version></dependency></dependencies><properties><spring.security.version>3.1.0.RELEASE</spring.security.version><log4j.version>1.2.12</log4j.version></properties><build><finalName>securityfirstdemo</finalName></build>
</project>

2>.在web.xml 里面添加spring security过滤器,添加代码如下:

<filter>  <filter-name>springSecurityFilterChain</filter-name>  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>  <filter-name>springSecurityFilterChain</filter-name>  <url-pattern>/*</url-pattern>
</filter-mapping>

我们使用了DelegatingFilterProxy过滤器, 然后拦截了所有的请求(因为是/*)

3>在web.xml将spring security的配置加入到spring的上下文中, spring-security的配置文件名为:applicationContext-Security.xml,在web.xml添加的代码如下:

<context-param><param-name>contextConfigLocation</param-name><param-value>WEB-INF/applicationContext-Security.xml</param-value>
</context-param>
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

4>一个最简单的spring security配置的如下,配置在applicationContext-Security.xml文件中,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context   http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"><!--auto-config等于true,他会自己给你一个登录页面,http基本认证和退出功能 --><!--拦截所有的请求,当我们具备了ROLE_SPITTER角色才可以进行访问 --><http auto-config="true"><intercept-url pattern="/**" access="ROLE_SPITTER" /></http><!--配置内存用户存储 --><!--通过user-service元素来创建一个用户服务 --><user-service id="userService"><user name="zhangsan" password="12" authorities="ROLE_SPITTER" /><user name="lisi" password="14" authorities="ROLE_AA" /></user-service><!--将用户服务装配到认证管理器中 --><authentication-manager><authentication-provider user-service-ref="userService"></authentication-provider></authentication-manager>
</beans:beans>

所有的认证和权限控制全部通过配置文件来实现,这里面的内容才是spring security的主要所在。

对上面的配置的稍作讲解:
      a.将auto-config属性配置为true好处,

我们可以得到他的免费的一些赠品,配置为true之后sping security会为我们提供一个额外的登录页,HTTP基本认证和退出功能,实际上,将auto-config属性配置为true等价于下面这样显示的配置的特性:

<http><form-login/><http-basic/><logout /><intercept-url pattern="/**" access="ROLE_SPITTER" />
</http>

b.<intercept-url>元素

<intercept-url>元素是实现请求级别的一道防线,他的pattern属性定义了对传入的请求要进行匹配的URL模式,如果请求匹配这个模式的话,<intercept-url>的安全规则就会启用。

就是表示访问某个请求,必须要某种权限,值得注意的是,在请求匹配上多个的时候,会从下往下进行匹配,知道匹配到第一个匹配的角色,就进行验证。

假设该应用有一些特定区域,只有管理员才能访问。为了实现这个点,我们可以在之前的那个条记录前插入如下的<intercept-url>:

 <http auto-config="true"><intercept-url pattern="/admin/** access="ROLE_ADMIN"" /><intercept-url pattern="/**" access="ROLE_SPITTER" /></http>

如果访问的是 "/admin/a.jsp"请求,其实两个都可以匹配的上,但是从上往下,由于先匹配到第一个,所有必须要"ROLE_ADMIN"角色才可以访问,虽然第二个可以匹配上,但是他不再往下匹配了。

c.为了方便期间直接在spring-security里的配置文件里面声明用户详细信息,用户的详细信息声明在<user-service>之中,每个能够登录的用户都会有一个<user>元素。属性name和password分别为指定了登录名和密码,同时authorities属性用于设置逗号分隔的权限列表--即允许用户做的事。从这spring-seccurity的配置中可以看得到,zhangsan可以对所有的URL有权限访问,而lisi没有。

d.<authentication-manager>元素会注册一个认证管理器。更确切的讲,他将注册一个ProviderManager实例。然后再将用户服务装配进来。

     2.3.2实例二,重写登录页面, 退出,且根据登录用户权限的不同,返回不同的首页

         在前面的例子中,我们可能会觉得得到了spring security提供的登录表单是赚了个大便宜,但是这个表单太简单了。且不美观,且我们改变不了其样式,所以一般我们会将其替换为自己设计的登录页面。

1.重写登录页面

为了设置自己的登录页面,我们需要配置<form-login>元素取代默认的行为:

<form-login login-page="/login" default-target-url="/employee/list"
authentication-failure-url="/login?error=true" />

登录页面通过“/login”进行登录。

登录成功后默认url访问/employee/list

登录失败后url访问/login?error=true

2.添加退出,让其退出到自己定义的页面去

<!--退出成功后调转的页面  -->
<logout invalidate-session="true" logout-success-url="/login" />

让其的session失效。

注销成功后转向:/login。

3.更加登录用户的权限不同返回不同的页面:

在登录成功之后,去取出当前登录用户的角色。然后判断其中有什么角色,更加角色来返回不同的页面,这样,不同的角色就只能够看到自己对应权限的页面。

@RequestMapping("/employee")
public class EmployeeController {@AutowiredEmployeeService employeeService;/** 查看所有的员工的信息*/@RequestMapping("/list")public String getallemployee(Model model) {List<Employee> lists = employeeService.findall();// 注意:用的是字符串,对应对象的形式,就是如下形式// model.addAttribute(string arg0, Object arg1)model.addAttribute("list", lists);//获得当前登录用户的角色列表Set<String> roles = AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities());if(roles.contains("ROLE_ADMIN")){return "home";}else if(roles.contains("ROLE_USER")){return "user/home";}else{   //这儿有一个 ROLE_ANONYMOUS 系统提供的匿名身份的用户return "redirect:/login";}}
}

下面这个语句是获得当前登录用户拥有的权限,是一个数组

SecurityContextHolder.getContext().getAuthentication().getAuthorities()

      下面语句是将当前用户的权限转成集合

AuthorityUtils.authorityListToSet(userAuthorities)

2.4基于数据库的管理用户和角色来使用spring security(企业一般是用这种)

      在上面我们所讲的两个例子中,我们的用户信息和权限信息都存在xml中,这是为了演示如何使用最小的配置就可以使用spring security。而实际开发中,用户基本信息和权限信息通常都是存储在数据库中,为此下面我们通过如下实例来说明企业是怎么使用spring security的。

    实例三,用户信息存储在数据库中,不同的角色访问的资源不一样,管理员对所有的有访问权限,而普通用户只对基本的有访问权限,

       一般会重写系统提供的UserDetailsService接口,然后根据前端传过来的用户名去数据库查询出基本信息根据数据库其权限给其添加权限

        其余都与上面一致就不再此说明了,只写这个接口的代码:


@Service("userServiceImpl")
public class UserServiceImpl implements UserService, UserDetailsService {@Autowiredprivate UserDao userdao;public List<DBUser> userquery(String username) {return userdao.userquery(username);}public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {UserDetails deuser = null; try {  // 搜索数据库以匹配用户登录名.  // 我们可以通过dao使用JDBC来访问数据库  List<DBUser> luser=userdao.userquery(username);if(luser == null )return deuser;DBUser user =  luser.get(0);// Populate the Spring User object with details from the dbUser  // Here we just pass the username, password, and access level  // getAuthorities() will translate the access level to the correct  // role type  //注意这个user是userDetail包里面的类//而dbuser也是userDetail包里面的类deuser = new User(user.getUsername(), user.getPassword().toLowerCase(), true, true, true, true,getAuthorities(user.getAccess()));  } catch (Exception e) {  throw new UsernameNotFoundException("Error in retrieving user");  }  return deuser;
}@SuppressWarnings("deprecation")public Collection<GrantedAuthority> getAuthorities(Integer access) {  List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);  // 所有的用户默认拥有ROLE_USER权限   authList.add(new GrantedAuthorityImpl("ROLE_USER"));  // 如果参数access为1.则拥有ROLE_ADMIN权限  if (access.compareTo(1) == 0) {         authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));  }  //返回权限列表,像管理员账号,zhangsan。返回的authList的值为 :[ROLE_USER, ROLE_ADMIN],而普通用户返回的值为[ROLE_USER]return authList;  }  }

这里要注意:这儿我们从数据库查询出来该用户的基本信息和权限信息之后,将其构建了一个user

deuser = new User(user.getUsername(), user.getPassword().toLowerCase(), true, true, true, true,getAuthorities(user.getAccess()));

这个user实现了UserDetails接口,主要存储了当前用户的用户名,密码,权限之类的信息,后面当用户访问对应的url的时候,会去这儿取这些数据,然后比较该用户是否拥有这个权限。这些是spring security框架做的事。

3.spring security的工作执行原理

1)web容器启动加载系统资源和权限列表

2)用户发出请求

3)过滤器拦截

4)取得请求资源所需权限

5)匹配用户拥有权限和请求权限,如果用户没有权限执行第六步,否则执行第七步

6)登录

7)验证并授权

其执行工作原理图如下:

4.用spring security防止session固化欺骗      

Session fixation attack(会话固定攻击)是利用服务器的session不变机制,借他人之手获得认证和授权,然后冒充他人。如果应用程序在用户首次访问它时为每一名用户建立一个匿名会话,这时往往就会出现会话固定漏洞。然后,一旦用户登录,该会话即升级为通过验证的会话。最初,会话令牌并未被赋予任何访问权限,但在用户通过验证后,这个令牌也具有了该用户的访问权限。

防止会话固定攻击,可以在用户登录成功后重新创建一个session id,并将登录前的匿名会话强制失效。Spring Security默认即可防止会话固定攻击。

转载于:https://my.oschina.net/u/1540325/blog/517481

Spring Security学习总结相关推荐

  1. spring security 学习三-rememberMe

    spring security 学习三-rememberMe 功能:登录时的"记住我"功能 原理: rememberMeAuthenticationFilter在security过 ...

  2. spring security 学习二

    spring security 学习二 doc:https://docs.spring.io/spring-security/site/docs/ 基于表单的认证(个性化认证流程): 一.自定义登录页 ...

  3. spring security 学习一

    spring security 学习一 1.配置基本的springboot web项目,加入security5依赖,启动项目 浏览器访问,即可出现一个默认的登录页面 2.什么都没有配置 登录页面哪里来 ...

  4. Spring security 学习 (自助者,天助之!)

    自己努力,何必要强颜欢笑的求助别人呢?  手心向下不求人! Spring security学习有进展哦: 哈哈! 1.页面都是动态生产的吧! 2.设置权限:  a:pom.xml配置jar包 b:cr ...

  5. Spring Security学习(二)

    以下配置基于表单登录配置 自定义配置登录页面 @Override protected void configure(HttpSecurity http) throws Exception {http. ...

  6. Spring Security 学习-环境搭建(一)

    首先说明一下基础环境的配置: JDK:1.8.0_144 IDE:STS(spring官方提供的基于eclipse的开发工具) :具体工具请自行搜索下载安装这里不做过多解释 1 搭建Spring Se ...

  7. Spring Security学习 详细

    Spring Security 是一个提供身份验证.授权和防止常见攻击的框架.凭借对保护命令式和反应式应用程序的一流支持,它是保护基于 Spring 的应用程序的事实标准. Spring Securi ...

  8. SpringBoot + Spring Security 学习笔记(一)自定义基本使用及个性化登录配置

    官方文档参考,5.1.2 中文参考文档,4.1 中文参考文档,4.1 官方文档中文翻译与源码解读 SpringSecurity 核心功能: 认证(你是谁) 授权(你能干什么) 攻击防护(防止伪造身份) ...

  9. spring security——学习笔记(day05)-实现自定义 AuthenticationProvider身份认证-手机号码认证登录

    目录 5.2 自定义 Provider 身份认证 5.2.1 编码思路和疑问 5.2.2 创建用户信息配置类 PhonePasswordAuthenticationToken 5.2.2 修改自定义的 ...

最新文章

  1. 32位处理器是什么意思
  2. 瘫痪小姐姐“自主”行走视频火了,曾借助轮椅完成舞蹈表演,网友:灵魂是战士...
  3. 数据库死锁的解决办法
  4. jquery1.9学习笔记 之选择器(基本元素五)
  5. MyEclipse Build path contains duplicate entry
  6. dev的编辑器不支持getchar吗_“两头婚兴起”:你支持不娶不嫁,孩子随父姓也随母姓吗?...
  7. 小型elf Hello,World程序
  8. 模拟电子电路技术基础 | 常用半导体器件
  9. 错误 LNK1104 无法打开文件“C:\Users\Administrator\Desktop\新建文件夹\ConsoleApplication1\x64\Debug\ConsoleApplicat
  10. 什么是CPU Die?
  11. (干货,建议收藏)备战2021年软考中级网络工程师-02操作系统
  12. python风控模型举例_一文搞定风控模型6大核心指标(附代码)
  13. 阿里资深技术专家:如何对复杂的业务系统进行解耦和重构?
  14. 树莓派python控制两个舵机_利用树莓派,光敏电阻和小型舵机实现自动获取 《最终幻想 X HD重制版》 连续避雷200次奖杯...
  15. java开发微信公众号图片上传功能,不吃透都对不起自己
  16. 基于PLC音乐喷泉控制系统设计音乐喷泉组态设计音乐喷泉
  17. 太阳能路灯c语言程序,基于单片机的智能太阳能路灯控制系统的设计方案
  18. 最大信息系数MIC的python代码
  19. Openbravo架构分析
  20. uniapp点击回复弹起键盘输入

热门文章

  1. python3.7魔塔游戏_基于Funcode平台的“火锅版魔塔”游戏开发与设计
  2. 在odoo服务器文件夹,在windows10上安装odoo12开发环境的方法
  3. php7.1 集成php fpm,LNMP建站教程(2):安装 PHP 7.1 与 PHP7.1-FPM以及与Nginx集成
  4. html5代码_深入解读HTML5移动应用程序开发!
  5. 公众号jdk 获取手机号_怎样快速获取使用国庆节公众号文章的素材和模板
  6. 机器人编程python代码_自己动手开发智能聊天机器人完全指南(附python完整源码)...
  7. 织梦根目录感染abc.php,织梦SEO优化:织梦dedecms根目录下robots.txt文件设置详解! - 张俊SEO...
  8. VB 获取光标在TextBox、RichTextBox中所在的位置
  9. 右侧交易稳健获利的指标
  10. 干货整理!10个Python图像处理工具,入门必看,提效大法 | 资源