Spring Security简介

Spring Security是 Spring提供的安全认证服务的框架。 使用Spring Security可以帮助我们来简化认证

和授权的过程。官网:https://spring.io/projects/spring-security

属于Spring家族一员,使用这个框架必须基于Spring

对应的maven坐标:

    <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>5.0.5.RELEASE</version> </dependency>

常用的权限框架除了Spring Security,还有Apache的shiro框架。

Spring Security基本入门

配置web.xml:在web.xml中主要配置SpringMVC的DispatcherServlet和用于整合第三方框架的

DelegatingFilterProxy,用于整合Spring Security。

      <filter> <!--DelegatingFilterProxy用于整合第三方框架 整合Spring Security时过滤器的名称必须为springSecurityFilterChain, 否则会抛出NoSuchBeanDefinitionException异常因为框架底层会根据这个过滤器名称获取一个Bean对象(Security的过滤器),它会加载很多的BeanSpring会根据传入的值,确定加载的对象,这个值是Spring容器中定义好的名称--> <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> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-security.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>

配置spring-security.xml:主要配置Spring Security的拦截规则和认证管理器

        <!-- http:用于定义相关权限控制,指定哪些资源不需要进行权限校验,可以使用通配符--><!-- 配置那些资源匿名可以访问(不需要登录)--><security:http security="none" pattern="/pages/a.html"/><!-- pages包下所有资源都可以访问--><security:http security="none" pattern="/pages/**"/><!--http:用于定义相关权限控制auto-config:是否自动配置设置为true时框架会提供默认的一些配置,例如提供默认的登录页面、登出 处理等设置为false时需要显示提供登录表单配置,否则会报错use-expressions:用于指定intercept-url中的access属性是否使用表达式来描述权限表达式:hasRole('ROLE_ADMIN')ROLE_ADMIN:普通字符串,建议与数据库角色或者权限关键字保持一致--><security:http auto-config="true" use-expressions="true"><security:headers><!--设置在页面可以通过iframe访问受保护的页面,默认为不允许访问--><security:frame-options policy="SAMEORIGIN"></security:frame-options></security:headers><!--intercept-url:定义一个拦截规则pattern:对哪些url进行权限控制,/** 表示拦截所有请求access:在请求对应的URL时需要什么权限,默认配置时它应该是一个以逗号分隔的角色列表,请求的用户只需拥有其中的一个角色就能成功访问对应的URL默认三种取值:IS_AUTHENTICATED_ANONYMOUSLY :不用登录可以访问资源IS_AUTHENTICATED_REMEMBERED: 只有自动登录才可以访问资源IS_AUTHENTICATED_FULLY: 只有登录成功才可以访问资源--><security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" /><!--只要认证通过就可以访问--> <security:intercept-url pattern="/index.jsp" access="isAuthenticated()" /> <security:intercept-url pattern="/a.html" access="isAuthenticated()" /> <!--拥有add权限就可以访问b.html页面--> <security:intercept-url pattern="/b.html" access="hasAuthority('add')" /><!--拥有ROLE_ADMIN角色就可以访问c.html页面--> <security:intercept-url pattern="/c.html" access="hasRole('ROLE_ADMIN')" /> <security:intercept-url pattern="/**" access="hasRole('角色1' or '角色2')" /><security:intercept-url pattern="/**" access="hasAnyRole('角色1','角色2')" /><!--method="POST":必须POST请求requires-channel="https":必须是https协议--> <security:intercept-url pattern="/**" method="POST" requires-channel="https"/><!--指定端口号--> <security:port-mappings><security:port-mapping http="666" https="888"/></security:port-mappings><!--拥有ROLE_ADMIN角色就可以访问d.html页面, 注意:此处虽然写的是ADMIN角色,框架会自动加上前缀ROLE_--> <security:intercept-url pattern="/d.html" access="hasRole('ADMIN')" /><!-- 如果要使用自己页面作为登录页面,必须配置登录表单,页面提交的登录表单请求由框架负责处理--><!--login-page:指定登录页面访问URLusername-parameter:指定用户名输入框,参数与表单保持一致,不写,表单name必须是usernamepassword-parameter:指定密码输入框,参数与表单保持一致,不写,表单name必须是passwordlogin-processing-url:指定表单的提交地址,请求default-target-url:登录成功,默认跳转页面authentication-failure-url:登录失败,默认跳转页面authentication-success-forward-url:登录成功,转发到这个页面如果两个登录成功跳转页面属性不写,那么登陆成功之后会跳转到本来请求的页面--><security:form-loginlogin-page="/login.html"username-parameter="username"password-parameter="password"login-processing-url="/login.do"default-target-url="/index.html"authentication-failure-url="/login.html"authentication-success-forward-url="/pages/a.html" /><!--csrf:对应CsrfFilter过滤器,disabled:是否启用CsrfFilter过滤器,框架默认提交csrf一串字符串,验证是否为框架自带的,如果使用自定义登录页面需要关闭此项,框架验证不通过,认为不是合法请求,登录操作会被禁用(403)--> <security:csrf disabled="true"/></security:http><!--authentication-manager:认证管理器,用于处理认证操作--><security:authentication-manager><!--authentication-provider:认证提供者,执行具体的认证逻辑配置认证的用户和密码,完成认证,必须告诉框架正确的用户名和密码是什么,对应的权限有哪些框架才可以拿着用户输入的用户名密码和配置的用户名密码比较可以直接写死用户名密码和权限,也可以配置Bean对象,从数据库获取但是Bean对象必须实现UserDetailsService接口--><security:authentication-provider user-service-ref="userService"><!--user-service:用于获取用户信息,提供给authentication-provider进行认证--><security:user-service><!--user:定义用户信息,可以指定用户名、密码、角色,后期可以改为从数据库查询 用户信息{noop}:表示当前使用的密码为明文authorities:权限--><security:user name="admin"password="{noop}admin"authorities="ROLE_ADMIN"/></security:user-service></security:authentication-provider></security:authentication-manager><bean id="userService" class="com.lx.service.SpringSecurityUserService"/></beans>

要从数据库动态查询用户信息,就必须按照spring security框架的要求提供一个实现

UserDetailsService接口的实现类,并按照框架的要求进行配置即可。框架会自动调用实现类中的方法

并自动进行密码校验。

public class SpringSecurityUserService implements UserDetailsService {// 根据用户名查询用户信息@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {System.out.println("用户输入的用户名:" + s);return null;}}

实现流程

  • 浏览器指定发送请求login.do,配置<security:form-login login-processing-url="/login.do"/>,一旦发送请求,框架自动拦截,接收用户名和密码

  • 框架定义好了接口UserDetailsService,指定方法loadUserByUsername,只需要实现此接口,框架会自己去调用方法,

  • 返回用户对象org.springframework.security.core.userdetails.User,框架定义好的user,框架自己判断用户名密码是否正确

  • 查询Dao,根据用户名查询,没有密码,密码框架拿着,也就是要求用户表,用户名必须唯一

Spring Security对密码进行加密

bcrypt:将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理

salt问题

加密后的格式一般为:

    $2a$10$/bTVvqqlH9UiE0ZJZ7N2Me3RIgUCdgMheyTgV0B4cMCSokPa.6oCa

加密后字符串的长度为固定的60位。其中:$是分割符,无意义;2a是bcrypt加密版本号;10是cost的

值;而后的前22位是salt值;再然后的字符串就是密码的密文了。

每次生成的密文不一样

实现步骤:

在spring-security.xml文件中指定密码加密对象

<!--认证管理器,用于处理认证操作--><security:authentication-manager><!--认证提供者,执行具体的认证逻辑--><security:authentication-provider user-service-ref="userService"><!--指定密码加密策略--><security:password-encoder ref="passwordEncoder" /></security:authentication-provider></security:authentication-manager><!--配置密码加密对象--><bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />@Autowiredprivate BCryptPasswordEncoder passwordEncoder;// 使用bcrypt提供的方法对密码进行加密user.setPassword(passwordEncoder.encode("admin"));

注解方式权限控制

spring-security.xml文件中配置

<!--开启spring注解使用--><context:annotation-config/><!--开启springMVC注解使用--><mvc:annotation-driven/><!--配置组件扫描,用于扫描Controller--><context:component-scan base-package="com.itheima.controller"/><!--开启注解方式权限控制--> <security:global-method-security pre-post-annotations="enabled" />

创建Controller类并在Controller的方法上加入注解进行权限控制

    @RestController@RequestMapping("/hello")public class HelloController {@RequestMapping("/add")// 表示用户必须拥有add权限才能调用当前方法@PreAuthorize("hasAuthority('add')")// 先执行方法,在进行权限校验@PostAuthorize("hasAuthority('CHECKITEM_DELETE')")public String add(){System.out.println("add.......");return "success";}@RequestMapping("/delete")//表示用户必须拥有ROLE_ADMIN角色才能调用当前方法@PreAuthorize("hasRole('ROLE_ADMIN')")public String delete(){System.out.println("delete.......");return "success";}}

获取用户登录的用户名

     // 获取当前登录用户的用户名@RequestMapping("/getUsername")public Result getUsername(){// Spring security完成认证后,会将当前用户信息保存到框架提供的上下文对象,存入session中User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();System.out.println("user = " + user);if (user != null){String username = user.getUsername();return new Result(true, MessageConstant.GET_USERNAME_SUCCESS,username);}return new Result(false, MessageConstant.GET_USERNAME_SUCCESS);}

退出登录

         <!--logout:退出登录logout-url:退出登录操作对应的请求路径logout-success-url:退出登录后的跳转页面invalidate-session:销毁session--> <security:logout logout-url="/logout.do"logout-success-url="/login.html"invalidate-session="true"/>

错误信息返回

    security:access-denied-handler ref='bean对象'// 错误信息类必须实现AccessDeniedHandler接口// 重写handle方法异步请求,响应回去数据都是异步请求回调函数中转换Json处理中文乱码httpServletResponse.setContentType("application/json;charset=utf-8")

【Spring框架家族】Spring--Security权限控制密码加密相关推荐

  1. maven 构建 springmvc + spring security 权限控制示例

    2019独角兽企业重金招聘Python工程师标准>>> maven 构建 springmvc + spring security 权限控制示例. 介绍 :Spring Securit ...

  2. 8.Spring Security 权限控制

    Spring Security权限控制可以配合授权注解使用,具体有哪些注解可以参考Spring-Security保护方法.接着上一节,要开启这些注解,只需要在Spring Security配置文件中添 ...

  3. Spring 框架(Spring Framework)使用详解

    概述 Spring 体系概述 Spring 是于2003年兴起的一个 full-stack 轻量级的 Java 开源框架,由 Rod Johnson 创建,使用 Spring 可以更快.更轻松.更安全 ...

  4. spring框架教程 Spring开发实例 spring mvc视频教程下载

    基于SpringMVC.MyBatis.FreeMarker架构实战CMS大型门户网站(自定义模板) spring框架教程 Spring开发实例 spring mvc视频教程下载地址: http:// ...

  5. 什么是spring框架?spring框架到底有什么用?spring框架到底做了些什么?

    什么是spring框架,spring框架究竟有什么用呢?我们可以用spring框架来做些什么呢?这是我今天要说的内容. 当然,百度spring框架会出现一大堆spring框架的介绍,以及IOC和AOP ...

  6. Spring Boot 之 RESRful API 权限控制

    一.为何用RESTful API 1.1 RESTful是什么? RESTful(Representational State Transfer)架构风格,是一个Web自身的架构风格,底层主要基于HT ...

  7. 大数据WEB阶段Spring框架(一)IOC控制反转、DI注入依赖

    Spring-IOC.DI 零.Spring简介 Spring官网:http://projects.spring.io/spring-framework Jar包的下载地址:http://repo.s ...

  8. Spring框架学习-Spring和IOC概述

    一:什么是Spring框架? spring是一个分层的javase/EEfull-stack(一站式)轻量级的java开源框架.是为了解决企业开发的复杂性而创建的.框架的主要优势是分层架构,Sprin ...

  9. IdaP02: springboot security权限控制篇

    通过狂神发布在B站的视频,了解到spring security(以下简称ss)在权限控制的强大好用,故学之. 一.详细例子 数据库 pom.xml 导入必要的包 <!-- security和th ...

最新文章

  1. fusioncharts相关问题
  2. [转]HDR渲染器的实现(基于OpenGL)
  3. Spring MVC 完整示例
  4. php多态性和继承是什么意思,封装 继承 多态的区别
  5. du的原理 linux_Linux 文件系统管理
  6. php进阶面向对象及tp5,TP5实战技巧---开发思路 引路造桥
  7. 格式化 SQL 来提高效率
  8. vant组件做表格_vue实现简单表格组件
  9. mysqldump备份过程中都干了些什么
  10. 强悍修改WIN7的文件夹背景(修改DLL)
  11. 2021百度之星程序设计大赛-初赛一部分题目总结
  12. VMware卸载后再安装提示无法打开注册表项 UNKNOWN\Components\…解决办法
  13. 手机内存LPDDR4X、LPDDR4、LPDDR3的区别 ICMAX告诉你
  14. 抖音便捷小空调特效 html+css+js
  15. 谷歌新政策的搜索字词紧密变体怎么应对?
  16. dede标签属性(转载)
  17. 上海镇保城保四金比例
  18. 向量点积衡量相似度_余弦距离、欧氏距离和杰卡德相似性度量的对比分析
  19. 【软件测试】软考-2022软件评测师考试心得
  20. C++ 什么时候调用析构函数和构造函数

热门文章

  1. Sun副总裁:绿色数据中心需分四步走
  2. Android中用GridView实现九宫格的两种方法
  3. hadoop MapReduce实例解析
  4. 九度OJ 朋友圈 并查集
  5. 后台开发经典书籍--图解http
  6. 创建守护进程关键步骤
  7. sprintf,sscanf,snprintf
  8. QT4到QT5的变化!
  9. javaweb:session
  10. linux系统管理命令,压缩命令