更多内容,前往IT-BLOG

一、Spring Security 简介


Spring Security 是一个能够为基于 Spring 的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring 应用上下文中配置的 Bean,充分利用了Spring IoC,DI(控制反转 Inversion of Control ,DI:Dependency Injection 依赖注入)和 AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

二、Spring Security 入门Demo


【1】创建 Maven工程(war形式):spring-security-demo
【2】修改 pom.xml目录,如下:

  1 <!-- 集中定义依赖版本号 -->
2 <properties>
3 <junit.version>4.12</junit.version>
4 <spring.version>4.2.4.RELEASE</spring.version>
5 <pagehelper.version>4.0.0</pagehelper.version>
6 <servlet-api.version>2.5</servlet-api.version>
7 <dubbo.version>2.8.4</dubbo.version>
8 <zookeeper.version>3.4.7</zookeeper.version>
9 <zkclient.version>0.1</zkclient.version>
10 <mybatis.version>3.2.8</mybatis.version>
11 <mybatis.spring.version>1.2.2</mybatis.spring.version>
12 <mybatis.paginator.version>1.2.15</mybatis.paginator.version>
13 <mysql.version>5.1.32</mysql.version>
14 <druid.version>1.0.9</druid.version>
15 <commons-fileupload.version>1.3.1</commons-fileupload.version>
16 <freemarker.version>2.3.23</freemarker.version>
17 <activemq.version>5.11.2</activemq.version>
18 <security.version>3.2.3.RELEASE</security.version>
19 <solrj.version>4.10.3</solrj.version>
20 <ik.version>2012_u6</ik.version>
21 </properties>
22 <dependencies>
23 <dependency>
24 <groupId>org.springframework</groupId>
25 <artifactId>spring-core</artifactId>
26 <version>${spring.version}</version>
27 </dependency>
28 <dependency>
29 <groupId>org.springframework</groupId>
30 <artifactId>spring-web</artifactId>
31 <version>${spring.version}</version>
32 </dependency>
33
34 <dependency>
35 <groupId>org.springframework</groupId>
36 <artifactId>spring-webmvc</artifactId>
37 <version>${spring.version}</version>
38 </dependency>
39
40 <dependency>
41 <groupId>org.springframework</groupId>
42 <artifactId>spring-context-support</artifactId>
43 <version>${spring.version}</version>
44 </dependency>
45
46 <dependency>
47 <groupId>org.springframework</groupId>
48 <artifactId>spring-test</artifactId>
49 <version>${spring.version}</version>
50 </dependency>
51
52 <dependency>
53 <groupId>org.springframework</groupId>
54 <artifactId>spring-jdbc</artifactId>
55 <version>${spring.version}</version>
56 </dependency>
57
58 <dependency>
59 <groupId>org.springframework.security</groupId>
60 <artifactId>spring-security-web</artifactId>
61 <version>4.1.0.RELEASE</version>
62 </dependency>
63
64 <dependency>
65 <groupId>org.springframework.security</groupId>
66 <artifactId>spring-security-config</artifactId>
67 <version>4.1.0.RELEASE</version>
68 </dependency>
69
70 <dependency>
71 <groupId>javax.servlet</groupId>
72 <artifactId>servlet-api</artifactId>
73 <version>2.5</version>
74 <scope>provided</scope>
75 </dependency>
76
77 </dependencies>
78 <build>
79 <plugins>
80 <!-- java编译插件 -->
81 <plugin>
82 <groupId>org.apache.maven.plugins</groupId>
83 <artifactId>maven-compiler-plugin</artifactId>
84 <version>3.2</version>
85 <configuration>
86 <source>1.7</source>
87 <target>1.7</target>
88 <encoding>UTF-8</encoding>
89 </configuration>
90 </plugin>
91 <plugin>
92 <groupId>org.apache.tomcat.maven</groupId>
93 <artifactId>tomcat7-maven-plugin</artifactId>
94 <configuration>
95 <!-- 指定端口 -->
96 <port>9090</port>
97 <!-- 请求路径 -->
98 <path>/</path>
99 </configuration>
100 </plugin>
101 </plugins>
102 </build>

注意:如果只是给自己的项目中嵌入 Spring Security 安全框架,只需要添加如下两个 jar 包即可。

 1 <dependency>
2 <groupId>org.springframework.security</groupId>
3 <artifactId>spring-security-web</artifactId>
4 <version>4.1.0.RELEASE</version>
5 </dependency>
6
7 <dependency>
8 <groupId>org.springframework.security</groupId>
9 <artifactId>spring-security-config</artifactId>
10 <version>4.1.0.RELEASE</version>
11 </dependency>

【3】创建 web.xml 文件(通过 Spring Security 拦截需要处理的请求和引入 Spring Security 的配置文件)。

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xmlns="http://java.sun.com/xml/ns/javaee"
4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
5 version="2.5">
6 <!-- 引入spring-security框架的配置文件 -->
7 <context-param>
8 <param-name>contextConfigLocation</param-name>
9 <param-value>classpath:spring-security.xml</param-value>
10 </context-param>
11 <listener>
12 <listener-class>
13 org.springframework.web.context.ContextLoaderListener
14 </listener-class>
15 </listener>
16 <!-- 通过spring-security 内置的拦截器 springSecurityFilterChain 拦截 /* 的请求,名称不能修改,安全框架的入口配置 -->
17 <!-- 所有的请求通过拦截器(DelegatingFilterProxy)拦截后,找名为 springSecurityFilterChain 类进行逻辑处理,此类是spring security安全框架中所包含的类 -->
18 <filter>
19 <filter-name>springSecurityFilterChain</filter-name>
20 <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
21 </filter>
22 <filter-mapping>
23 <filter-name>springSecurityFilterChain</filter-name>
24 <url-pattern>/*</url-pattern>
25 </filter-mapping>
26 </web-app>

【4】创建 Spring Security 配置文件:spring-security.xml(与 web.xml 中引入的配置文件对应),代码中有配置的详细说明注解。

 1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- 此配置将Spring Seucrity设置成了默认标签,其他使用时,需要添加如下前缀beans或dubbo等 -->
3 <beans:beans
4 xmlns="http://www.springframework.org/schema/security"
5 xmlns:beans="http://www.springframework.org/schema/beans"
6 xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
7 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
8 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
9 http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
10 http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
11
12 <!-- 登录页面不能拦截 none任何角色都可访问
13 如果你没有设置登录页security="none" ,将会出现以下错误 :"重定向次数过多"因为登录页会被反复重定向-->
14 <http pattern="/*.html" security="none"></http>
15 <http pattern="/css/**" security="none"></http>
16 <http pattern="/img/**" security="none"></http>
17 <http pattern="/js/**" security="none"></http>
18 <http pattern="/plugins/**" security="none"></http>
19 <!-- 注意:如果是用户申请登录名的请求也不能拦截 -->
20 <http pattern="/seller/add.do" security="none"></http>
21 <!-- 拦截页面 -->
22 <!-- use-expressions -为是否使用 Spring 表达式语言( SpEL ),默认为true ,如果开启,则拦截的配置应该写成以下形式
23 <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
24 -->
25 <http use-expressions="false">
26 <!--
27 /* 表示的是该目录下的资源,只包括本级目录不包括下级目录
28 /** 表示的是该目录以及该目录下所有级别子目录的资源
29 -->
30 <intercept-url pattern="/**" access="ROLE_SELLER" />
31 <!-- form-login:开启表单登录,默认登录请求/login可以通过配置修改默认请求
32 always-use-default-target:指定了是否在身份验证通过后总是跳转到default-target-url属性指定的URL。
33 authentication-failure-url:登录失败,跳转页面 -->
34 <form-login login-page="/login.html"
35 default-target-url="/index.html"
36 authentication-failure-url="/login_error.html"
37 always-use-default-target="true" />
38 <!-- csrf disabled="true" 关闭csrf ,如果不加会出现错403 这种一般会自动生成在请求头信息中:
39 'X-CSRF-TOKEN'(相当于一个校徽)防止跨站点攻击,但只能jsp实现,html不能实现,因此需要关闭此功能
40 CSRF(Cross-site request forgery)跨站请求伪造,
41 也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。-->
42 <csrf disabled="true" />
43 <!-- 当页面中存在嵌入式iframe时,需要配置hears -->
44 <headers>
45 <frame-options policy="SAMEORIGIN" />
46 </headers>
47 <!-- 登出,页面只需要发送/logout请求就可会触发 也可以修改默认的处理,例如logout-url=""可以修改登出的请求-->
48 <logout />
49 </http>
50 <!-- Spring Security中 用户登录时认证管理器 -->
51 <!-- Spring Security是如何完成身份认证的?
52 ①、用户名和密码被过滤器获取到,封装成Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类。
53 ②、AuthenticationManager 身份管理器负责验证这个Authentication。
54 ③、认证成功后,AuthenticationManager身份管理器返回一个被填充满了信息的(包括上面提到的权限信息,身份信息,细节信息,但密码通常会被移除)Authentication实例。
55 ④、SecurityContextHolder安全上下文容器将第3步填充了信息的Authentication,
56 通过SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中。 -->
57 <authentication-manager>
58 <!-- user-service-ref 指向用户认证业务处理类,需要实现UserDetailsService接口-->
59 <!-- 如果测试,不想从数据库中获取用户,可以直接配置一个用户名和密码 ,特换掉如下authentication-provider内的配置即可。 -->
60 <authentication-provider>
61 <user-service>
62 <user name="admin" password="123456" authorities="ROLE_USER"/>
63 </user-service>
64 </authentication-provider>
65
66 <!-- <authentication-provider user-service-ref="userDetailServiceImpl">
67 对密码进行bcrypt加密,比较时需要解密后处理,bcrypt与MD5不同,
68 MD5加密后相同的密码生成相同的16位字符创,bcrybt相同的密码加密后生成不同的30位字符串,
69 相当于MD5+盐
70 <password-encoder hash="bcrypt"></password-encoder>
71 </authentication-provider> -->
72 </authentication-manager>
73 <!-- <beans:bean id="userDetailServiceImpl" class="com.pinyougou.shop.service.UserDetailServiceImpl">
74 当自己的项目需要使用另一个项目中的服务类时 ,需要通过dubbo引入项目 dubbo标签
75 <beans:property name="sellerService" ref="sellerService"></beans:property>
76 </beans:bean> -->
77
78
79 <!-- 引用dubbo sellerService服务:供登录用户业务处理类使用 -->
80 <!-- <dubbo:application name="pinyougou-shop-web" />
81 <dubbo:registry address="zookeeper://192.168.159.129:2181" />
82 <dubbo:reference id="sellerService"
83 interface="com.pinyougou.sellergoods.service.SellerService"></dubbo:reference> -->
84 </beans:beans>

【5】需要自己创建:login.html(登录页面 如下)、index.html(登录成功跳转页面)、login_error.html(登录失败跳转页面)

 1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8">
5 <title>登陆</title>
6 </head>
7 <body>
8 --欢迎登陆我的系统--
9 <form action="/login" method="post">
10 用户名:<input name="username"><br>
11 密码:<input name="password"><br>
12 <button>登陆</button>
13 </form>
14 </body>
15 </html>

三、项目实战中,后台业务逻辑实现重要代码摘取,供实战中使用


【1】配置文件中配置的,登录时用户名和密码的业务逻辑处理类(实现 UserDetailsService:框架自带的接口),注意:普通 demo 不需要此部分,主要用于真是环境登录逻辑的处理。

 1 public class UserDetailServiceImpl implements UserDetailsService {
2 //当通过配置文件的形式,引入服务类时需要设置set方法。
3 private SellerService sellerService;
4
5 public void setSellerService(SellerService sellerService) {
6 this.sellerService = sellerService;
7 }
8
9 @Override
10 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
11 //GrantedAuthority : 定义用户角色,需要实现的接口
12 List<GrantedAuthority> list =new ArrayList<>();
13 //用户添加角色,SimpleGrantedAuthority可以定义用户角色,实现了GrantedAuthority接口,
14 //格式必须以(ROLE_)开头
15 list.add(new SimpleGrantedAuthority("ROLE_SELLER"));
16 //从数据库中获取用户信息。
17 TbSeller seller = sellerService.findOne(username);
18 if(seller != null) {
19 //返回username:传过来的参数。seller.getPassword:数据库中获取到的用户密码。
20 //list:用户的所有角色,可以从数据库中获取
21 return new User(username, seller.getPassword(), list);
22 }else {
23 return null;
24 }
25 }
26 }

【2】BCrypt 加密过程(配置中说明了 BCrypt 与 MD5 的区别)。

 1 @RequestMapping("/add")
2 public Result add(@RequestBody TbSeller seller){
3 try {
4 //BCrypt加密使用的对象BCryptPasswordEncoder
5 BCryptPasswordEncoder cryptPasswordEncoder = new BCryptPasswordEncoder();
6 //使用encode方法对传入的密码加密,返回30位的字符串
7 String encode = cryptPasswordEncoder.encode(seller.getPassword());
8 //业务处理:接入对象中
9 seller.setPassword(encode);
10 //调用服务层,入库
11 sellerService.add(seller);
12 return new Result(true, "增加成功");
13 } catch (Exception e) {
14 e.printStackTrace();
15 return new Result(false, "增加失败");
16 }
17 }

四、当程序中需要用户名时,可通过 SecurityContextHolder 对象获取


SecurityContextHolder 用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保存在 SecurityContextHolder 中。SecurityContextHolder 默认使用 ThreadLocal  策略来存储认证信息。看到 ThreadLocal 也就意味着,这是一种与线程绑定的策略。Spring Security 在用户登录时自动绑定认证信息到当前线程,在用户退出时,自动清除当前线程的认证信息。但这一切的前提,是你在 web 场景下使用 Spring Security。
☏ 因为身份信息是与线程绑定的,所以可以在程序的任何地方使用静态方法获取用户信息。一个典型的获取当前登录用户的姓名的例子如下所示:getAuthentication() 返回了认证信息。

1 @RequestMapping("/name")
2 public Map<String, String> getName(){
3 //获取登录名
4 String name = SecurityContextHolder.getContext().getAuthentication().getName();
5 Map<String, String> map = new HashMap<>();
6 map.put("loginName", name);
7 return map;
8 }

☏ Authentication 源码:

1 package org.springframework.security.core;// <1>
2 public interface Authentication extends Principal, Serializable { // <1>
3 Collection<? extends GrantedAuthority> getAuthorities(); // <2>
4 Object getCredentials();// <2>
5 Object getDetails();// <2>
6 Object getPrincipal();// <2>
7 boolean isAuthenticated();// <2>
8 void setAuthenticated(boolean var1) throws IllegalArgumentException;
9 }

【1】Authentication 是 Spring Security 包中的接口,直接继承自 Principal 类,而 Principal 是位于 java.security 包中的。可以见得,Authentication 在 Spring Security 中是最高级别的身份/认证的抽象。
【2】由这个顶级接口,我们可以得到用户拥有的权限信息列表,密码,用户细节信息,用户身份信息,认证信息。
authentication.getPrincipal() 返回了一个 Object,我们将 Principal 强转成了Spring Security 中最常用的 UserDetails,这在Spring Security 中非常常见,接口返回 Object,使用 instanceof 判断类型,强转成对应的具体实现类。接口详细解读如下:
getAuthorities():权限信息列表,默认是GrantedAuthority接口的一些实现类,通常是代表权限信息的一系列字符串。
getCredentials():密码信息,用户输入的密码字符串,在认证过后通常会被移除,用于保障安全。
getDetails():细节信息,web应用中的实现接口通常为 WebAuthenticationDetails,它记录了访问者的 ip地址和 sessionId的值。
getPrincipal():最重要的身份信息,大部分情况下返回的是UserDetails接口的实现类,也是框架中的常用接口之一。


 ----关注公众号,获取更多内容----

Spring Security 框架使用的更多相关文章

  1. Spring Security框架进阶、自定义登录

      1.Spring Security框架进阶 1.1 Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安 ...

  2. Spring Security框架入门

    1.Spring Security框架入门 1.1 Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框 ...

  3. Spring Security框架中踢人下线技术探索

    1.背景 在某次项目的开发中,使用到了Spring Security权限框架进行后端权限开发的权限校验,底层集成Spring Session组件,非常方便的集成Redis进行分布式Session的会话 ...

  4. Spring Security框架下Restful Token的验证方案

    项目使用Restful的规范,权限内容的访问,考虑使用Token验证的权限解决方案. 验证方案(简要概括): 首先,用户需要登陆,成功登陆后返回一个Token串: 然后用户访问有权限的内容时需要上传T ...

  5. 1. Spring Security 框架简介

    官网:https://projects.spring.io/spring-security/Spring Security 是强大的,且容易定制的实现认证,与授权的基于 Spring 开发的框架.Sp ...

  6. Spring Security框架下实现两周内自动登录"记住我"功能

    本文是Spring Security系列中的一篇.在上一篇文章中,我们通过实现UserDetailsService和UserDetails接口,实现了动态的从数据库加载用户.角色.权限相关信息,从而实 ...

  7. 在Spring Security框架下JWT的实现细节原理

    一.回顾JWT的授权及鉴权流程 在笔者的上一篇文章中,已经为大家介绍了JWT以及其结构及使用方法.其授权与鉴权流程浓缩为以下两句话 授权:使用可信用户信息(用户名密码.短信登录)换取带有签名的JWT令 ...

  8. SpringBoot 整合Spring Security框架

    引入maven依赖 <!-- 放入spring security依赖 --> <dependency> <groupId>org.springframework.b ...

  9. Spring Security安全框架

    今天来简单介绍一下Spring Security安全框架 简介 Spring Security 提供了基于javaEE的企业应有个你软件全面的安全服务.这里特别强调支持使用SPring框架构件的项目, ...

  10. 使用 Spring Security 保护 Web 应用的安全

    安全一直是 Web 应用开发中非常重要的一个方面.从安全的角度来说,需要考虑用户认证和授权两个方面.为 Web 应用增加安全方面的能力并非一件简单的事情,需要考虑不同的认证和授权机制.Spring S ...

随机推荐

  1. 天龙八部<三联版>三

    虚竹经历这么多事情,只想回少林寺,在面馆遇到出来玩的阿紫被阿紫调戏而破了荤戒.随后丁春秋到来,抓到阿紫,恰好慕容复也来到面馆,二人相斗,阿紫在打斗过程中被丁春秋刺瞎双眼,但却被游坦之救走, 最后慕容复 ...

  2. Hackintool查看CFG锁显示空白

    Hackintool是黑苹果配置的得力工具,通过在Hackintool > 工具 > 从AppleIntelInfo中获取 可以看到cfg是否成功解锁.但是如果点击该按钮后输入密码执行CP ...

  3. Vue实现组件化的基本思路

    Vue.js(以下简称Vue)是时下流行的前端开发库,一般搭配其插件Vue-Router,Vuex一起使用,行业中称为Vue全家桶. Vue使用了MVVM的理念,将表现层(DOM)和数据层进行了分离, ...

  4. python3中的负数整除、求余问题

    注:小白问题,大神们请忽略先看示例,非整除: >>> -10/3-3.3333333333333335>>> 10/-3-3.3333333333333335> ...

  5. 解决IOS上传竖向照片会旋转90度的问题

    // 解决IOS上传竖向照片会旋转90度的问题 rotate() { const that = this; that.imgOrientation = 1; let Orientation = nul ...

  6. Java流程控制1

    Scanner对象 java.util.Scanner 通过Scanner类来获取用户输入 next()和nextline()来获取输入的字符串,读取前我们一般需要使用hasnext()和hasnex ...

  7. 项目:口令保管箱,批处理文件配置.bat

    #! python3 import sys import pyperclip PASSWORDS = {'email': 'F7minlBDDuvMJuxESSKHFhTxFtjVB6', 'blog ...

  8. Java的由来

    Java 发展史 1.1.起源 20 世纪 90 年代,单片式计算机系统诞生,单片式计算机系统不仅廉价,而且功能强大,使用它 可以大幅度提升消费性电子产品的智能化程度. SUN 公司为了抢占市场先机, ...

  9. Python数据可视化,自适应浏览器

    pyecharts生成的html默认是靠左上显示的需要生成的文件居中显示,且能根据浏览器窗口大小自动调整需要修改html当然,如果你是熟悉html,且只是临时少量生成表格的话,每次生成完后手动修改ht ...

  10. 整数划分问题(Java递归)

    整数划分问题(Java递归) 文章目录 整数划分问题(Java递归) 0. 问题描述 1.递归式 2.代码 3.参考 0. 问题描述 整数划分问题 将正整数n表示成一系列正整数之和:n=n1+n2+- ...