个人博客网:https://wushaopei.github.io/    (你想要这里多有)

1、Spring Security 权限管理框架介绍

简介: Spring Security 提供了基于javaEE的企业应有个你软件全面的安全服务。这里特别强调支持使用SPring框架构件的项目,Spring框架是企业软件开发javaEE方案的领导者。

Spring Security 的两个目标: “认证” 与“授权”。

  • 认证”,是建立一个他声明的主题的过程(一个“主体”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统)。
  • 授权” 指确定一个主体是否允许在你的应用程序执行一个动作的过程。为了抵达需要授权的店,主体的身份已经有认证过程建立。这个概念是通用的而不只在Spring Security中。

在SpringSecurity 中,请求进入后会被拦截器拦截到,并交由认证管理器首先处理;这是在身份验证层,Spring Security 的支持多种认证模式。包括 Basic、Digest、X.509、LDAP、Form(基于表单的认证) 等多种HTTP 认证。

浅析:

Basic 认证:在HTTP1.0提出的认证方法,针对特定的用户和资源,需要提供特定的密码认证后方可访问,其中密码是使用明文传输的;一个请求到来时,浏览器弹出对话框,让用户输入用户名和密码,并用BASE 64 进行编码进行传输,服务器接受并解析这些信息,并认证通过,才会允许继续访问。

Digest认证: 解决Basic 认证的安全问题,当访问时,浏览器依旧弹出对话框,让用户输入用户名和密码,浏览器会对用户名、密码、HTTP请求方法、被请求资源的URI进行组合后进行MD5运算,然后把计算得到的摘要信息发送给服务器;服务器获取报文头部相关认证信息后获取到 username ,同时获取到密码,同样对用户名、密码、HTTP请求方法、被请求资源的URI进行组合后和 response 进行比较,如果相同,才算认证通过。

2、Spring Security 常用权限拦截器:

主要功能性拦截器有 11 个, FilterChainProxy 对拦截器进行过滤操作并代理执行!

3、Spring Security 项目 Demo

(1)环境搭建及使用

  1. 基于Spring Boot + Spring Security 环境
  2. 常用 Case 实现

(2)创建SpringBoot 工程

(3)整合SpringSecurity 依赖

	        <!--springsecurity 主要依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>

(4)主启动类配置:

@RestController          //返回响应体为json
@SpringBootApplication
@EnableAutoConfiguration //扫描Bean注入到容器中
public class Bootstrap { public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
} @RequestMapping("/") // 测试接口
public String home (){
return "hello spring boot";
} @RequestMapping("/hello") //测试接口
public String hello (){
return "hello spring boot";
}
}

(5)配置 Servlet 初始化

/**
* @ClassName ServletInitializer 告诉程序,项目启动时从 Bootstrap 开始
* @Description TODO
* @Author wushaopei
* @Date 2019/9/19 10:30
* @Version 1.0
*/
public class ServletInitializer extends SpringBootServletInitializer { @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application){
return application.sources(Bootstrap.class);
}
}

(6)启动SpringBoot 项目- - run 主启动类:

启动SpringBoot 项目进行接口访问时,弹出登录界面,说明SpringSecurity生效了

4、SpringSecurity拦截配置:

注意:在 3  的基础上,对工程进一步配置:

(1)创建 SpringSecurityConfig 类管理 拦截配置:

@Configuration     // 将Bean 放到容器中管理
@EnableWebSecurity // 用于将Security 生成 Bean
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { /*
* 接口请求拦截
**/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() //安全请求策略
.antMatchers("/").permitAll() //可放行请求配置
.anyRequest().authenticated() //其他请求进行拦截
.and()
.logout().permitAll() // 注销任意访问
.and()
.formLogin();
http.cors().disable();
}
/*
* 前端拦截
* */
@Override
public void configure(WebSecurity web){
// 忽视 js 、css 、 images 后缀访问
web.ignoring().antMatchers("/js/**","/css/**","/images/**");
}
}

该 SpringSecurityConfig 继承 WebSecurityConfigurerAdapter 类,并重写 configure(HttpSecurity http)和 configure(WebSecurity web)两个方法,分别针对 接口请求 静态页面 资源进行拦截。

接口请求: ip:port/  的请求一律通过,主要进入到 Bootstrap 中的 RequestMapping(“/”)接口中;并对 “/”后带有标识地址的请求进行拦截认证;

静态资源: 此处对静态 js 、css、images 三者进行放行。

效果截图:

配置 SpringSecurity 后,默认可以通过 “/” 的接口请求; 而当进行 如“/hello”接口请求时会被拦截进行验证

5、基于SpringSecurity 权限管理 Case 实操

权限管理 Case 的需求有两个要求:

  1. 第一点 :只要能登录即可;
  2. 第二点:有指定的角色,每个角色有指定的权限.

(1)只要能登录即可,功能体现:

在SpringSecurityConfig.java中配置用户信息:

/*
* 告诉程序,系统中有个用户 用户名为 admin ,密码为 admin 角色为 ADMIN
* */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN"); }

注意 :

在springboot使用spring security 做权限管理 ,使用内存用户验证,会返回无响应报错:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

解决方法:

这是因为Spring boot 2.0.3引用的security 依赖是 spring security 5.X版本,此版本需要提供一个PasswordEncorder的实例,否则后台汇报错误:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
并且页面毫无响应。
因此,需要创建PasswordEncorder的实现类。

创建PasswordEncorder 实体类后可通过两种方式完成明文验证通过:

第一种:直接在配置好的 PasswordEncorder 类上添加 @Component 装配 MyPasswordEncoder 为Bean 注入到容器即可;

@Component
public class MyPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
} @Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence.toString());
}
}

然后继续使用

  /*
* 告诉程序,系统中有个用户 用户名为 admin ,密码为 admin 角色为 ADMIN
* */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { //可以设置内存指定的登录的账号密码,指定角色
//不加.passwordEncoder(new MyPasswordEncoder())或者注入该类的Bean
//就不是以明文的方式进行匹配,会报错
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
}

进行 密码明文登录,可以成功

第二种:在auth.inMemoryAuthentication()后面使用.passwordEncoder(new MyPasswordEncoder())对登录信息进行包装后提交即可;这样也可以成功

//这样,页面提交时候,密码以明文的方式进行匹配。
auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder()).withUser("wsp").password("wsp").roles("ADMIN");

推荐: 最好是使用第一种 装载成 Bean 后注入容器,对于开发效率更高,也更便捷。

(2)有指定的角色,每个角色有指定的权限,功能体现:

① 创建接口 role1() 并对其添加 @PreAuthorize("hasRole('ROLE_ADMIN')")  以进行角色拦截

    @PreAuthorize("hasRole('ROLE_ADMIN')") // 角色拦截校验注解
@RequestMapping("/roleAuth")
public String role1(){ return "roleAuth";
}

(2)角色拦截 - - 功能解析:

@PreAuthorize("hasRole('ROLE_ADMIN')") 注解说明:

②并在 SpringSecurityConfig.java 中创建新用户,以提供测试:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//可以设置内存指定的登录的账号密码,指定角色
//不加.passwordEncoder(new MyPasswordEncoder())
//就不是以明文的方式进行匹配,会报错
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
auth.inMemoryAuthentication().withUser("demo").password("demo").roles("DEMO");
.passwordEncoder(new MyPasswordEncoder())。
//这样,页面提交时候,密码以明文的方式进行匹配。
auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder()).withUser("wsp").password("wsp").roles("ADMIN");
}

③ 创建好接口后,进行登录尝试,发现,使用 用户为 demo ,角色 为 DEMO 依旧可以通过该接口

问题解析:

这是因为还需要再添加一个@EnableGlobalMethodSecurity(prePostEnabled = true) 注解到 启动器上,以让 @PreAuthorize("hasRole('ROLE_ADMIN')") 这个注解生效,完整 启动类代码如下:

@RestController
@SpringBootApplication
@EnableAutoConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class Bootstrap { public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
@RequestMapping("/")
public String home (){
return "hello spring boot";
}
@RequestMapping("/hello")
public String hello (){
return "hello spring boot";
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping("/roleAuth")
public String role1(){
return "roleAuth";
}
}

添加注解后

使用 demo 进行登录:

使用admin进行登录:

(3)数据库管理实现

通过数据库获取用户信息进行登录认证

创建 MyUserService.java类,并装载 Bean 到 容器中,在SpringSecurityConfig.java 中进行配置:

@Component
public class MyUserService implements UserDetailsService{
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
return null;
}
}

SpringSecurityConfig.java 中 configure(AuthenticationManagerBuilder auth)方法修改为通过注入MyUserService 的Bean实现数据库查询

    @Autowired
private MyUserService myUserService; @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserService); // 通过注入 MyUserService 的方式实现数据库查询用户信息的登录认证 }

密码的自定义验证:

创建 MyPasswordEncoder 类,实现 PasswordEncoder 接口类;重写 encode(CharSequence obj和 matches(CharSequence obj,String str) 方法:

@Component
public class MyPasswordEncoder implements PasswordEncoder { private final static String SALT = "wenmin"; @Override
public String encode(CharSequence charSequence) { return MD5Util.MD5Encode(charSequence.toString(),SALT);
} @Override
public boolean matches(CharSequence rawPassword, String encodedPassword) { return MD5Util.isPasswordValid(encodedPassword,rawPassword.toString(),SALT);
}
}

说明:第一个是加密的方法,第二个是匹配密码,具体操作是加密方法加密后与原始密码在匹配方法中进行匹配

底层逻辑解析:

passwordEncoder. isPasswordValid(userDetails.getPassword(), presentedPassword, salt) 这个实现是在接口PasswordEncoder的实现类MessageDigestPasswordEncoder中实现的。 

MessageDigestPasswordEncoder类:
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
String pass1 = "" + encPass;
String pass2 = encodePassword(rawPass, salt); return pass1.equals(pass2);
} 其中 encodePassword(rawPass, salt)方法如下:
public String encodePassword(String rawPass, Object salt) {
String saltedPass = mergePasswordAndSalt(rawPass, salt, false); MessageDigest messageDigest = getMessageDigest(); byte[] digest; try {
digest = messageDigest.digest(saltedPass.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 not supported!");
} // "stretch" the encoded value if configured to do so
for (int i = 1; i < iterations; i++) {
digest = messageDigest.digest(digest);
} if (getEncodeHashAsBase64()) {
return new String(Base64.encode(digest));
} else {
return new String(Hex.encode(digest));
}
}
使用的是MD5加密方法。

引入自定义的登录信息验证器

auth.userDetailsService(myUserService).passwordEncoder(new MyPasswordEncoder());

相关注解说明:

@PreAuthorize("hasRole('ROLE_ADMIN')")  方法调用前进行权限检查
@PostAuthorize("hasRole('')")           方法调用后进行权限检查
@PreFilter("")                          方法调用前针对集合类参数或返回值进行过滤
@PostFilter("") 方法调用后针对集合类参数或返回值进行过滤

6、Spring Security 的优缺点

优点:

提供了一套安全框架,而且这个框架是可以用的;

提供了很多用户认证的功能,实现相关接口即可,节约大量开发工作;

基于spring,易于集成到 spring 项目中,且封装了许多方法。

缺点:

配置文件多,角色被“编码”到配置文件盒源文件中,RBAC 不明显;

对于系统中用户、角色、权限之间的关系,没有可操作的界面;

大数据量情况下,几乎不可用。

https://github.com/wushaopei/SPRING_BOOT/tree/master/Spring-boot-Security

快速搭建基于Spring Boot + Spring Security 环境的更多相关文章

  1. 如何快速搭建基于python+appium的自动化测试环境

    首先申明本文是基本于Python与Android来快速搭建Appium自动化测试环境: 主要分为以下几个步骤: 前提条件: 1)安装与配置python环境,打开 Python官网,找到“Downloa ...

  2. 快速搭建Spring Boot + Apache Shiro 环境

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.Apache Shiro 介绍及概念 概念:Apache Shiro是一个强大且易用的Java安全框 ...

  3. 基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目

    一.前言 最近整合Spring Boot+Spring Security+JWT+Vue 完成了一套前后端分离的基础项目,这里把它开源出来分享给有需要的小伙伴们 功能很简单,单点登录,前后端动态权限配 ...

  4. 256.Spring Boot+Spring Security: MD5是加密算法吗?

    说明 (1)JDK版本:1.8 (2)Spring Boot 2.0.6 (3)Spring Security 5.0.9 (4)Spring Data JPA 2.0.11.RELEASE (5)h ...

  5. 255.Spring Boot+Spring Security:使用md5加密

    说明 (1)JDK版本:1.8 (2)Spring Boot 2.0.6 (3)Spring Security 5.0.9 (4)Spring Data JPA 2.0.11.RELEASE (5)h ...

  6. Spring Boot+Spring Security:获取用户信息和session并发控制

    说明 (1)JDK版本:1.8(2)Spring Boot 2.0.6(3)Spring Security 5.0.9(4)Spring Data JPA 2.0.11.RELEASE(5)hiber ...

  7. Spring Boot+Spring Security+JWT 实现 RESTful Api 认证(一)

    标题 Spring Boot+Spring Security+JWT 实现 RESTful Api 认证(一) 技术 Spring Boot 2.Spring Security 5.JWT 运行环境 ...

  8. Spring boot +Spring Security + Thymeleaf 认证失败返回错误信息

    [Please make sure to select the branch corresponding to the version of Thymeleaf you are using] Stat ...

  9. Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台

    Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台: https://gitee.com/leecho/cola-cloud

随机推荐

  1. 【x64软路由】OpenWrt(LEDE) 20200329编译 反追踪 抗污染 加速 PSW 无缝集成 UPnP NAS

    固件说明 基于Lede OpenWrt R2020.3.19版本(源码更新截止20200329)Lienol Feed及若干自行维护的软件包 结合家庭x86软路由场景需要定制 按照家庭应用场景对固件及 ...

  2. 【Hadoop离线基础总结】Hue与Hive集成

    目录 1.更改hue的配置hue.ini 2.启动hive的metastore以及hiveserver2服务 3.启动hue进程,查看Hive是否与Hue集成成功 1.更改hue的配置hue.ini ...

  3. 关于redis内存分析,内存优化

    对于redis来说,什么是最重要的? 毋庸置疑,是内存. 一.reids 内存分析 redis内存使用情况:info memory 示例: 可以看到,当前节点内存碎片率为226893824/20952 ...

  4. android progressbar 自定义图片匀速旋转

    项目中需要使用圆形进度条进行数据加载的显示,所以需要两个步骤 1:自定义progressbar滚动图片 2:匀速旋转图片 步骤一:自定义progressbar图片 <ProgressBar an ...

  5. 对background: url("~assets/img/common/collect.svg") 0 0/14px 14px 的理解

    需求:给收藏数字前面通过::before伪元素添加图标 相关代码: .goods-info .collect { position: relative; } .goods-info .collect: ...

  6. 【Socket编程】【第一节】【Socket基本原理和套接字】

    参考http://c.biancheng.net/view/2351.html 一.scoket套接字(告诉你使用哪种数据传输方式) 这个世界上有很多种套接字(socket),比如 DARPA Int ...

  7. python实现三级菜单源代码

    8月4号早晨天气晴,继续学习‘Alex’的python视频,写了用字典实现三级菜单的代码,都是循环和判断比较lower,废话不多说直接贴码: #!/user/bin/env python #-*-co ...

  8. Java内存区域与内存溢出异常——深入理解Java虚拟机 笔记一

    Java内存区域 对比与C和C++,Java程序员不需要时时刻刻在意对象的创建和删除过程造成的内存溢出.内存泄露等问题,Java虚拟机很好地帮助我们解决了内存管理的问题,但深入理解Java内存区域,有 ...

  9. spark机器学习从0到1协同过滤算法 (九)

      一.概念 协同过滤算法主要分为基于用户的协同过滤算法和基于项目的协同过滤算法.   基于用户的协同过滤算法和基于项目的协同过滤算法 1.1.以用户为基础(User-based)的协同过滤 用相似统 ...

  10. JetBrains PyCharm 2018.2.4 x64 工具里如何安装bs4

    第一步:点击File->Settings 第二步:选择Project:workplace-->Project Interpreter,然后再点击右上角的"+"按钮进入下 ...