SpringSecurity概念以及整合ssm框架

news2025/2/28 23:53:50

基本概念

Spring中提供安全认证服务的框架,认证:验证用户密码是否正确的过程,授权:对用户能访问的资源进行控制

在这里插入图片描述

用户登录系统时我们协助 SpringSecurity 把用户对应的角色、权限组装好,同时把各个资源所要求的权限信息设定好,剩下的“登录验证”、“权限验证”等等工作都交给SpringSecurity。

权限管理过程中的相关概念

主体

英文单词:principal

使用系统的用户或设备或从其他系统远程登录的用户等等。简单说就是谁使用系统谁就是主体。

认证

英文单词:authentication

权限管理系统确认一个主体的身份,允许主体进入系统。简单说就是“主体”证明自己是谁。笼统的认为就是以前所做的登录操作。

授权

英文单词:authorization

将操作系统的“权力”“授予”“主体”,这样主体就具备了操作系统中特定功能的能力。

所以简单来说,授权就是给用户分配权限。

使用

pom文件中加入spring security的依赖

<!-- SpringSecurity 对 Web 应用进行权限管理 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.10.RELEASE</version>
</dependency>
<!-- SpringSecurity 配置 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.10.RELEASE</version>
</dependency>
<!-- SpringSecurity 标签库 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>4.2.10.RELEASE</version>
</dependency>

web.xml加入SpringSecurity控制权限的Filte

    <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>

加入配置类

package com.atguigu.crowd.mvc.config;

import com.atguigu.crowd.constant.CrowdConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration// 表示当前类是一个配置类
@EnableWebSecurity// 启用web环境下权限控制
// prePostEnabled = true的作用:保证@PreAuthorize、@PreAuthorize、@PreFilter、@PostFilter生效
@EnableGlobalMethodSecurity(prePostEnabled = true)// 启用全局方法权限控制
public class WebApplicationConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    CrowdUserDetailsService crowdUserDetailsService;
    @Autowired
    BCryptPasswordEncoder passwordEncoder;

    @Override
    protected void configure(HttpSecurity security) throws Exception {
        security
                .authorizeRequests()
                .antMatchers("/admin/to/login/page.html")
                .permitAll()// 允许无条件访问登录请求
                .antMatchers("/bootstrap/**", "/crowd/**", "/css/**",
                        "/fonts/**", "/img/**", "/jquery/**", "/layer/**",
                        "/script/**", "/ztree/**")
                .permitAll()// 允许无条件访问静态文件
                .antMatchers("/admin/get/page.html")
                .hasAuthority("user:get") // 拥有user:get权限才可以访问用户维护
                .antMatchers("/role/to/role/page.html")
                .hasRole("经理")// 拥有经理角色才可以访问角色维护
                .antMatchers("/admin/get/page.html")
                .access("(hasAnyRole('经理')) and hasAuthority('user:get')")
                .anyRequest()
                .authenticated()// 其他任何资源都要登录才可以访问
                .and()
                .exceptionHandling()
                .accessDeniedHandler(new AccessDeniedHandler() {
                    @Override
                    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                        request.setAttribute("exception", new
                                Exception(CrowdConstant.MESSAGE_ACCESS_DENIED));
                        request.getRequestDispatcher("/WEB-INF/error/system_error.jsp").forward(request, response);
                    }
                })// 出现异常的处理方法
                .and()
                .csrf()
                .disable()// 禁用跨站请求伪造功能
                .formLogin()// 开启表单登录功能
                .loginPage("/admin/to/login/page.html")// 设置默认的登录页面
                .loginProcessingUrl("/security/do/login.html")// 处理登录请求的地址
                .defaultSuccessUrl("/admin/to/admin-main/page.html")// 登录成功后要前往的地址
                .usernameParameter("loginAcct")// 账号的请求参数名
                .passwordParameter("userPswd")// 密码的请求参数名
                .and()
                .logout()
                .logoutUrl("/security/do/logout.html")// 退出登录访问的地址
                .logoutSuccessUrl("/admin/to/login/page.html")// 退出页面成功要去的地址
        ;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {
//        builder
//                .inMemoryAuthentication()// 开启内存认证
//                .withUser("tom")// 设置账号
//                .password("123123")// 设置密码
//                .roles("ADMIN")// 设置角色
//        ;

        // 使用基于数据库的认证
        builder.userDetailsService(crowdUserDetailsService).passwordEncoder(passwordEncoder);
    }
}

注解@PreAuthorize规定角色权限

需要在SpringSecurity中标注

@EnableGlobalMethodSecurity(prePostEnabled = true)

    /**
     * 根据关键字查询分页信息
     *
     * @param pageNum  当前页码
     * @param pageSize 每页显示条数
     * @param keyword  关键字
     * @return 分页信息
     */
    @PreAuthorize("hasAuthority('role:get') or hasAnyRole('经理')")// 需要有role:get权限才可以访问
    @ResponseBody
    @GetMapping("/role/get/page/info.json")
    public ResultEntity<PageInfo<Role>> getPageInfo(
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "4") Integer pageSize,
            @RequestParam(value = "keyword", defaultValue = "") String keyword
    ) {
        // 获取页面数据
        PageInfo<Role> pageInfo = roleService.getRoleByKeyword(pageNum, pageSize, keyword);
        // 如果出现异常,dispatcherServlet会进行处理
        return ResultEntity.successWithData(pageInfo);
    }

@PostAuthorize

先执行方法然后根据方法返回值判断是否具备权限。

例如:查询一个 Admin 对象,在@PostAuthorize 注解中和当前登录的 Admin 对象进行比较,如果不一致,则判断为不能访问。实现“只能查自己”效果。

@PostAuthorize("returnObject.data.loginAcct == principal.username")

使用 returnObject 获取到方法返回值,使用 principal 获取到当前登录用户的主体对象。

通过故意写错表达式,然后从异常信息中发现表达式访问的是下面这个类的属性:

org.springframework.security.access.expression.method.MethodSecurityExpressionRoot

@PreFilter

在方法执行前对传入的参数进行过滤。只能对集合类型的数据进行过滤。

@PreFilter(value="filterObject%2==0")
@ResponseBody
@RequestMapping("/admin/test/pre/filter")
public ResultEntity<List<Integer>> saveList(@RequestBody List<Integer> valueList) {
return ResultEntity.successWithData(valueList);
}

@PostFilter

在方法执行后对方法返回值进行过滤。只能对集合类型的数据进行过滤。

CrowdUserDetailsService

其实返回的就是SpringSecurity的User对象,只是做了一层封装。

package com.atguigu.crowd.mvc.config;

import com.atguigu.crowd.entity.Admin;
import com.atguigu.crowd.entity.Role;
import com.atguigu.crowd.service.api.AdminService;
import com.atguigu.crowd.service.api.AuthService;
import com.atguigu.crowd.service.api.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class CrowdUserDetailsService implements UserDetailsService {
    @Autowired
    private AdminService adminService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private AuthService authService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1、根据账号名称查找Admin对象
        Admin admin = adminService.getAdminByLoginAcct(username);
        // 2、获取adminId
        Integer adminId = admin.getId();
        // 3、根据adminId查询角色信息
        List<Role> roles = roleService.getAssignedRole(adminId);
        // 4、根据adminId查询权限名字信息
        List<String> auths = authService.getAssignedAuthNameByAdminId(adminId);
        // 5、创建集合对象来存储GrantedAuthority
        ArrayList<GrantedAuthority> authorities = new ArrayList<>();
        // 6、遍历存入角色消息
        for (int i = 0; i < roles.size(); i++) {
            // 需要加前缀,因为SpringSecurity就是通过ROLE_来区分是角色还是权限
            String roleName = "ROLE_" + roles.get(i).getName();
            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(roleName);
            authorities.add(authority);
        }
        // 7、遍历存入权限信息
        for (int i = 0; i < auths.size(); i++) {
            String authName = auths.get(i);
            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(authName);
            authorities.add(authority);
        }
        // 8、封装到SecurityAdmin对象中,它继承了SpringSecurity的User类
        SecurityAdmin securityAdmin = new SecurityAdmin(admin, authorities);
        return securityAdmin;
    }
}

BCryptPasswordEncoder

它是SpringSecurity自带的密码加密与验证的类。

页面元素控制

取出当前登录对象

<%--需要导入taglib--%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>
<%--principal 是我们自己封装的 SecurityAdmin 对象(返回的SpringSecurity的User对象)--%>
<security:authentication property="principal.originalAdmin.userName"/>

标签库控制

<%--需要导入taglib--%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>
<security:authorize access="hasRole('经理')">
    <!-- 开始和结束标签之间是要进行权限控制的部分。检测当前用户是否有权限,有权限
    就显示这里的内容,没有权限就不显示。 --> ……
</security:authorize>

access属性可以传入权限控制相关的表达式。

/>


### 标签库控制

```html
<%--需要导入taglib--%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>
<security:authorize access="hasRole('经理')">
    <!-- 开始和结束标签之间是要进行权限控制的部分。检测当前用户是否有权限,有权限
    就显示这里的内容,没有权限就不显示。 --> ……
</security:authorize>

access属性可以传入权限控制相关的表达式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/94218.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

毕业设计-基于大数据技术的旅游推荐系统-python

目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科…

前端基础(十一)_Float浮动、清除浮动的几种方法

浮动 1、什么是浮动&#xff1f; 目的&#xff1a;为了让多个块级元素在同一行显示&#xff1b; 文档流&#xff1a;可显示的对象在排列时所占的位置&#xff1b; 浮动&#xff1a;使元素脱离正常的文档流&#xff0c;按照指定的顺序&#xff0c;方向发生移动&#xff0c;直到…

疫情下景区管理

开发工具(eclipse/idea/vscode等)&#xff1a;idea 数据库(sqlite/mysql/sqlserver等)&#xff1a;mysql 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a;模块划分&#xff1a;公告类型、公告信息、用户信息、用户咨询、地区信息、景区信息、景区开放、景区预约、统计…

【Flask框架】——17 Flask蓝图

在一个Flask 应用项目中&#xff0c;如果业务视图过多&#xff0c;可否将以某种方式划分出的业务单元单独维护&#xff0c;将每个单元用到的视图、静态文件、模板文件等独立分开&#xff1f; 例如从业务角度上&#xff0c;可将整个应用划分为用户模块单元、商品模块单元、订单…

应急响应-windows/Linux主机加固

windows/Linux主机加固 1,账户安全 首先要确保电脑上的账户均为经常使用的账户&#xff0c;要禁止Guest用户&#xff0c;禁用其他无用账户&#xff0c;一段时间后无反馈即可删除&#xff0c;同时要留意是否有隐藏账户存在。 查看本地用户和组&#xff1a;右键此电脑>计算机管…

PG::FunboxEasy

nmap -Pn -p- -T4 --min-rate1000 192.168.58.111 nmap -Pn -p 22,80,33060 -sCV 192.168.58.111 查看80端口的页面&#xff0c;未发现可用信息。 对路径进行爆破 gobuster dir -u http://192.168.58.111/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt…

Vue3 —— 使用Vite配置环境变量

文章目录 一、为什么要配置环境变量?二、在Vite中配置环境变量 1.环境变量和模式2.环境变量3.生产环境替换4.env 文件总结一、为什么要配置环境变量? 在一个产品的前端开发过程中&#xff0c;一般来说会经历本地开发、测试脚本、开发自测、测试环境、预上线环境&#xff0c;然…

后疫情时代,VR全景创业的应用场景有哪些?

在数字化转型的进程中&#xff0c;VR技术可以帮助各个行业领域的企业商家更便捷地搭建沉浸式服务体验&#xff0c;帮助商家提高展示以及加快企业沟通效率。后疫情时代&#xff0c;企业数字化转型加速发展&#xff0c;VR技术已经成为企业云服务的标配工具&#xff0c;因此VR全景…

半入耳蓝牙耳机什么牌子好?音质最好的半入耳式蓝牙耳机

跑步或者游泳的时候带着耳机听音乐或者有声书&#xff0c;是一家很惬意舒心的事情&#xff0c;市面上有那么多的蓝牙耳机品牌&#xff0c;很多人在选购的时候总是犯了难&#xff0c;不知道哪款耳机值得入手&#xff0c;半入二的佩戴更加舒适&#xff0c;深受很多人的喜爱&#…

用于音频信号去噪的谱相减和陷波滤波的比较(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 谱相减减少背景&#xff08;加性&#xff09;噪声影响的最流行方法之一是谱相减。背景噪声是降低录音中语音质量和清晰度的最常…

const成员和static成员详解

const成员和static成员详解1.const成员函数2.static成员&#xff08;1&#xff09;静态成员变量&#xff08;2&#xff09;静态成员函数&#xff08;3&#xff09;静态成员使用场景1.const成员函数 将const修饰的“成员函数”称之为const成员函数&#xff0c;const修饰类成员函…

热点新品—类器官代谢组学

01为什么研究类器官如此重要&#xff1f; 类器官技术是近年来生物医学领域最具突破性的前沿技术之一&#xff0c;更是科技部发布了“十四五”国家重点研发计划的6个重点专项之一。因模型本身具有极高的创新性&#xff0c;深受基金申请和高分杂志的青睐。并且由于人源化类器官可…

让你室友、工友、小孩、断网的骚操作!ARP攻击演示!

前提&#xff1a; ① 、你需要 和 你室友处于同一个局域网&#xff0c;互相能ping通 ②、你需要知道你室友的IP ③、您可能需要一个linux 设备&#xff0c;手机也行&#xff08;需要安装termux 来执行命令&#xff09;、linux系统电脑、树莓派等都可以。 -----------------…

PCB入门学习—原理图的绘制2

目录 2.2 TEA5767音频模块的绘制 2.3 ENC28J60以太网模块的绘制 学习目录&#xff1a; 2.2 TEA5767音频模块的绘制 首先有个问题&#xff1a;为什么这个电容放在原理图上怎么移动也对不齐&#xff1f;&#xff1f; 解决方法&#xff1a;把原理图上的栅格这个东西设置成1mil…

【小甲鱼C语言】课后笔记第一章第七节——算数运算符

目录 1. 算术运算符 2. 何谓“目”&#xff1f; 3. 表达式 4. 类型转换 5.课后习题&#xff08;编程题&#xff09; 1. 算术运算符 C 语言通过提供大量的运算符来支持我们对数据进行处理&#xff0c;前边我们将一个值存放到变量中&#xff0c;使用的是赋值运算符&#xff…

lerna+rollup搭建vue组件库并发布到npm

一、框架介绍 1. lerna Lerna 是一个管理工具&#xff0c;用于管理包含多个软件包&#xff08;package&#xff09;的 JavaScript 项目。 目的是将大型代码仓库分割成多个独立版本化的软件包。 官网点这里 2. rollup Rollup 是一个 JavaScript 模块打包工具&#xff0c;可以将…

骨灰级精品,京东百万架构师亲码的MySQL内部笔记太硬核了

前言 MySQL是Java程序员面向高级的必备技能&#xff0c;很多朋友在面试时经常在这里折戟沉沙&#xff0c;饮恨不已。熟练掌握MySQL知识&#xff0c;在实践中具有很强的操作性&#xff0c;尤其是在互联网行业&#xff0c;不仅要写好代码、实现功能&#xff0c;而且还要在高并发…

P1983 [NOIP2013 普及组] 车站分级——拓扑排序+dp

[NOIP2013 普及组] 车站分级 题目描述 一条单向的铁路线上&#xff0c;依次有编号为 $1, 2, …, n $的 $n $个火车站。每个火车站都有一个级别&#xff0c;最低为 111 级。现有若干趟车次在这条线路上行驶&#xff0c;每一趟都满足如下要求&#xff1a;如果这趟车次停靠了火车…

二进制转化成十进制进行输出

给定两个十进制整数 : AAA,BBB 你需要把它们的二进制形式以十进制的运算法则相加输出结果。 例如&#xff1a; A3,B2A 3 , B 2A3,B2 的时候&#xff0c;AAA 的二进制表示是 : 111111 , BBB 的二进制表示是 101010 &#xff0c;你需要输出答案为 : 212121 输入描述: 一行两…

educoder:实验13 算法-穷举法和二分法

第1关&#xff1a;百钱百鸡 任务描述 我国古代数学家张丘建在《算经》一书中提出的数学问题&#xff1a;鸡翁一值钱五&#xff0c;鸡母一值钱三&#xff0c;鸡雏三值钱一。百钱买百鸡&#xff0c;问鸡翁、鸡母、鸡雏各几何&#xff1f; 相关知识 为了完成本关任务&#xff…