首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Security 权限控制

Security 权限控制

作者头像
张哥编程
发布于 2024-12-13 06:42:37
发布于 2024-12-13 06:42:37
20400
代码可运行
举报
文章被收录于专栏:云计算linux云计算linux
运行总次数:0
代码可运行

Security 权限控制

一、注解权限控制

1.1 启用注解配置

@EnableGlobalMethodSecurity分别有prePostEnabled、securedEnabled、jsr250Enabled三个字段,其中每个字段代码一种注解支持,默认为false,true为开启

在同一个应用程序中,可以启用多个类型的注解,但是只应该设置一个注解对于行为类的接口或者类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    ....
}

1.2 设置用户角色权限

Security中角色和权限设置保存的方式一样,但是使用方式不一样

角色

管理员/测试人员/普通用户

对应使用的代码是hasRole,授权代码需要加ROLE_前缀,controller上使用时根据需要可以不要加前缀

权限

执行的操作:路径访问权限 功能操作权限

对应使用的代码是hasAuthority,设置和使用时,名称保持一至即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    if(this.cname.equals("zs")){
        return AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN,add,select");
    }else{
        return AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_TEST,select");
    }
}

实际项目中,用户角色权限信息从数据库中获取

1.3 获取用户信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
	@RequestMapping("/user1")
    @ResponseBody
    public Object user1(){
        return SecurityContextHolder.getContext().getAuthentication();
    }

    @RequestMapping("/user2")
    @ResponseBody
    public Object user2(HttpServletRequest request){
        return request.getUserPrincipal();
    }

    @RequestMapping("/user3")
    @ResponseBody
    public Object user3(Principal principal){
        return principal;
    }

    @RequestMapping("/user4")
    @ResponseBody
    public Object user4(Authentication authentication){
        return authentication;
    }

1.4 在方法上添加注解

securedEnabled

安全注解

使用@Secured注解

@Secured注解是用来定义业务方法的安全配置。在需要安全的方法上指定 @Secured,并且只有那些角色/权限的用户才可以调用该方法。

@Secured缺点就是不支持Spring EL表达式。不够灵活。并且指定的角色必须以ROLE_开头,不可省略。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
	@Secured("ROLE_ADMIN")
    @RequestMapping("/m1")
    @ResponseBody
    public String m1(){
        return "m1";
    }

    @Secured({"ROLE_TEST"})
    @RequestMapping("/m2")
    @ResponseBody
    public String m2(){
        return "m2";
    }

    @Secured({"ROLE_ADMIN","ROLE_TEST"})
    @RequestMapping("/m3")
    @ResponseBody
    public String m3(){
        return "m3";
    }
jsr250Enabled

JSR-250注解

比较简单,在指定方法中使用方法注解@RolesAllowed,@DenyAll,@PermitAll

  • @DenyAll 全部拒绝
  • @PermitAll 全部通过
  • @RolesAllowed({"USER", "ADMIN"})
    • 代表标注的方法只要具有USER, ADMIN任意一种权限就可以访问。这里可以省略前缀ROLE_,实际的权限可能是ROLE_ADMIN。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    // 全部拒绝访问
    @DenyAll
    @RequestMapping("/m4")
    @ResponseBody
    public String m4(){
        return "m4";
    }

    // 可以访问
    @PermitAll
    @RequestMapping("/m5")
    @ResponseBody
    public String m5(){
        return "m5";
    }

    // 拥有角色可访问
    @RolesAllowed({"ROLE_ADMIN","ROLE_TEST"})
    @RequestMapping("/m6")
    @ResponseBody
    public String m6(){
        return "m6";
    }

    // 可省略ROLE_
    @RolesAllowed({"ADMIN","TEST"})
    @RequestMapping("/m7")
    @ResponseBody
    public String m7(){
        return "m7";
    }
prePostEnabled

前置注解

该注解更适合方法级的安全,也支持Spring 表达式语言,提供了基于表达式的访问控制

  • @PreAuthorize --适合进入方法之前验证授权
  • @PostAuthorize --检查授权方法之后才被执行
  • @PostFilter --在方法执行之后执行,而且这里可以调用方法的返回值,然后对返回值进行过滤或处理或修改并返回
  • @PreFilter --在方法执行之前执行,而且这里可以调用方法的参数,然后对参数值进行过滤或处理或修改
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@PreAuthorize("authentication.principal.username == 'tom' ")
@PreAuthorize("hasRole('ROLE_ADMIN')")

// 只能user角色可以访问
@PreAuthorize ("hasAnyRole('user')")

// user 角色或者 admin 角色都可访问
@PreAuthorize ("hasAnyRole('user') or hasAnyRole('admin')")

// 同时拥有 user 和 admin 角色才能访问
@PreAuthorize ("hasAnyRole('user') and hasAnyRole('admin')")

// 限制只能 id 小于 10 的用户
@PreAuthorize("#id < 10")
User findById(int id);

// 只能查询自己的信息
@PreAuthorize("principal.username.equals(#username)")
User find(String username);

// 限制只能新增用户名称为abc的用户
@PreAuthorize("#user.name.equals('abc')")
void add(User user)
    
// 查询到用户信息后,再验证用户名是否和登录用户名一致
@PostAuthorize("returnObject.name == authentication.name")
@GetMapping("/get-user")
public User getUser(String name){
    return userService.getUser(name);
}
// 验证返回的数是否是偶数
@PostAuthorize("returnObject % 2 == 0")
public Integer test(){
    // ...
    return id;
}

// 指定过滤的参数,过滤偶数
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> username)
    
@PostFilter("filterObject.id%2==0")
public List<User> findAll(){
    ...
    return userList;
}

表达

描述

hasRole([role])

返回true当前委托人是否具有指定角色。默认情况下,如果提供的角色不是以“ ROLE_”开头,则会添加该角色。可以通过修改defaultRolePrefixon来自定义DefaultWebSecurityExpressionHandler。

hasAnyRole([role1,role2])

返回true当前委托人是否具有提供的任何角色(以逗号分隔的字符串列表形式)。默认情况下,如果提供的角色不是以“ ROLE_”开头,则会添加该角色。可以通过修改defaultRolePrefixon来自定义DefaultWebSecurityExpressionHandler。

hasAuthority([authority])

true如果当前主体具有指定的权限,则返回。

hasAnyAuthority([authority1,authority2])

返回true当前委托人是否具有提供的任何角色(以逗号分隔的字符串列表形式)

principal

允许直接访问代表当前用户的主体对象

authentication

允许直接访问Authentication从SecurityContext

permitAll

总是评估为 true

denyAll

总是评估为 false

isAnonymous()

返回true当前委托人是否为匿名用户

isRememberMe()

返回true当前主体是否是“记住我”的用户

isAuthenticated()

true如果用户不是匿名的,则返回

isFullyAuthenticated()

返回true如果用户不是匿名或记得,我的用户

hasPermission(Object target, Object permission)

返回true用户是否可以访问给定权限的给定目标。例如,hasPermission(domainObject, 'read')

hasPermission(Object targetId, String targetType, Object permission)

返回true用户是否可以访问给定权限的给定目标。例如,hasPermission(1, 'com.example.domain.Message', 'read')

二、RBAC权限控制

RBAC(role-Based-access control),一般都是由 3个部分组成,一个是用户,一个是角色 ,一个是资源(菜单,按钮),然后就是 用户和角色的关联表,角色和资源的关联表

核心就是判断当前的用户所拥有的URL是否和当前访问的URL是否匹配。

2.1 创建校验类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component("rbacConfig")
public class RbacConfig {

    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        boolean hasPermission = false;
        
        Object principal = authentication.getPrincipal();// 获取登录用户的详细信息
        // 判断是否登录
        if (principal instanceof UserDetails) {
            // 类型转换
            MyUser myUser = (MyUser) principal;
			
            // 获取请求路径
            String uri = request.getRequestURI();
            
            // 获取用户权限并判断
            ......
        }
        
        return hasPermission;
    }
}

2.2 添加自定义的权限表达式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.authorizeRequests()
.anyRequest()
.access("@rbacConfig.hasPermission(request,authentication)")

@rbacService 就是声明的bean对象

三、支持跨域请求

3.1 添加跨域请求配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Configuration
public class GlobalCorsConfig {

    @Bean
    @Order("0")
    public CorsFilter corsFilter(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 允许请求带有验证信息
        corsConfiguration.setAllowCredentials(true);
        // 允许请求域名
        corsConfiguration.addAllowedOrigin("http://localhost:8081");
        // 允许请求头
        corsConfiguration.addAllowedHeader("*");
        // 允许请求方式
        corsConfiguration.setAllowedMethods(Arrays.asList("POST"));

        // 基于路径的苦于配置源
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }
}

3.2 修改配置支持跨域请求

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
				// 跨域资源共享
                .cors()
                .and()
                .csrf()
                .disable()
                .authorizeRequests()
                //处理跨域请求中的Preflight请求
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()

3.3 修改VUE携带验证信息

中文文档

https://www.kancloud.cn/yunye/axios/234845/

封装axios

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import axios from 'axios'

let http = axios.create({
    baseURL:"http://localhost:8088",
    withCredentials:true,
    timeout:5000,
    responseType:'json'
})

// 添加请求拦截器
http.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});

// 添加响应拦截器
http.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
}, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
});

export default http

修改引入的axios

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import http from './utils/Http'

Vue.prototype.$axios = http

四、设置权限不足异常

4.1 添加异常处理类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class AccessExceptionHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        httpServletResponse.setCharacterEncoding("UTF-8");

        httpServletResponse.setContentType("application/json");

        httpServletResponse.getWriter().println("{\"code\":403,\"message\":\"没有权限访问呀!\",\"data\":\"\"}");

        httpServletResponse.getWriter().flush();

    }
}

4.2 配置异常处理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
			http...
                .and()
				.exceptionHandling()
                .authenticationEntryPoint(authenticationError)
                .accessDeniedHandler(accessExceptionHandler)

4.3 配置登录异常处理

判断是否是ajax请求,ajax请求返回json

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class AuthenticationError implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        boolean isajax = false;

        String accept = httpServletRequest.getHeader("accept");
        if (accept != null && accept.indexOf("application/json") != -1)
        {
            isajax= true;
        }

        String xRequestedWith = httpServletRequest.getHeader("X-Requested-With");
        if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
        {
            isajax= true;
        }

        if(isajax){
            httpServletResponse.setCharacterEncoding("UTF-8");
            httpServletResponse.setContentType("application/json");
            httpServletResponse.getWriter().println("{\"code\":500,\"message\":\"用户名密码错误!\",\"data\":\"\"}");
            httpServletResponse.getWriter().flush();
        }else{
            httpServletResponse.sendRedirect("failure");
        }
    }
}

五、表结构

用户表

1001 zs 123...

角色表

R01 管理员 admin ....

用户角色关联表

1001 R01

模块表

P01 员工管理 /emp

角色模块表

R01 P01

R01 P02

功能表

G01 ADD

G02 SEELCT

角色功能关联表

R01 G01

R01 G02

(模块功能表)

六、前后端分离

前台访问后台接口获取数据信息,必须把登录用户的信息随着请求传递给后台接口

每一次请求响应都需要携带用户信息。

Token

后台:JWT

前台:VUEX,sessionstorage,localstrorage

权限控制

后台:注解,RBAC

前台:

  1. 保存用户的登录信息;
  2. 封装方法,判断用户是否有某个角色或者权限;

动态路由

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
php判断文件上传图片格式的实例详解
$type = $_FILES'image';//文件名 //$type = $this->getImagetype( $type ); $filetype = ['jpg', 'jpeg', 'gif', 'bmp', 'png']; if (! in_array($type, $filetype)) { return "不是图片类型"; }
用户2323866
2021/07/09
1.9K0
Upload-labs通关笔记(三)
Upload-labs是一个帮你总结所有类型的上传漏洞的靶场 项目地址:https://github.com/Tj1ngwe1/upload-labs 环境要求 若要自己亲自搭建环境,请按照以下配置环境,方可正常运行每个Pass。 配置项 配置 描述 操作系统 Window or Linux 推荐使用Windows,除了Pass-19必须在linux下,其余Pass都可以在Windows上运行 PHP版本 推荐5.2.17 其他版本可能会导致部分Pass无法突破 PHP组件 php_gd2,php_exif
网络安全自修室
2020/07/22
8730
上传伪技术~很多人都以为判断了后缀,判断了ContentType,判断了头文件就真的安全了。是吗?
今天群里有人聊图片上传,简单说下自己的经验(大牛勿喷) 0.如果你的方法里面是有指定路径的,记得一定要过滤../,比如你把 aa文件夹设置了权限,一些类似于exe,asp,php之类的文件不能执行,那么如果我在传路径的时候,前面加了一个../呢,这样这种服务器端的限制就跳过了。(DJ音乐站基本上都有这个问题,以及用某编辑器的同志) 1.常用方法:这种就是根据后缀判断是否是图片文件,需要注意的是这种格式:文件:1.asp;.jpg 1.asp%01.jpg 目录: 1.jpg/1.asp 1.jpg/1.
逸鹏
2018/04/10
1.3K0
上传伪技术~很多人都以为判断了后缀,判断了ContentType,判断了头文件就真的安全了。是吗?
10个 ThinkPHP 开发常用代码片段
在编写代码的时候有个神奇的汇总是好的!下面这里收集了 10+ PHP 代码片段,可以帮助你开发 PHP 项目。这些 PHP 片段对于 PHP 初学者也非常有帮助,非常容易学习,让我们开始学习吧~
php007
2019/11/18
8430
上传靶机实战之upload-labs解题
我们知道对靶机的渗透可以提高自己对知识的掌握能力,这篇文章就对上传靶机upload-labs做一个全面的思路分析,一共21个关卡。让我们开始吧,之前也写过关于上传的专题,分别为浅谈文件上传漏洞(客户端JS检测绕过) 浅谈文件上传漏洞(其他方式绕过总结)
雪痕@
2021/06/10
1.9K0
Upload-labs(1-15)详解
想到这也就知道是绕过方法中的黑名单绕过了,上面的不让上传,想到了可以上传.php5的文件,除了这个还有.phtml.phps .pht 但是要想上传后能执行,要在自己的apache的httpd.conf文件写入
ly0n
2020/11/04
7.6K0
Upload-labs(1-15)详解
PHP 文件上传代码审计
只验证MIME类型: 代码中验证了上传的MIME类型,绕过方式使用Burp抓包,将上传的一句话小马*.php中的Content-Type:application/php,修改成Content-Type: image/png然后上传.
王 瑞
2022/12/28
1.2K0
Upload-labs 通关学习笔记
使用障眼法,将PHP文件修改图像格式后直接上传;使用burp拦截该数据包,修改文件格式(后缀名)
Mirror王宇阳
2020/11/13
4.5K0
Upload-labs 通关学习笔记
Email系列(QQ邮箱 + 含附件的邮箱案例 + 项目实战)上
平台之大势何人能挡? 带着你的Net飞奔吧! http://www.cnblogs.com/dunitian/p/4822808.html 邮箱系列:https://github.com/duniti
逸鹏
2018/04/10
1.1K0
Email系列(QQ邮箱 + 含附件的邮箱案例 + 项目实战)上
[红日安全]Web安全Day5 - 任意文件上传实战攻防
大家好,我们是红日安全-Web安全攻防小组。此项目是关于Web安全的系列文章分享,还包含一个HTB靶场供大家练习,我们给这个项目起了一个名字叫 Web安全实战 ,希望对想要学习Web安全的朋友们有所帮助。每一篇文章都是于基于漏洞简介-漏洞原理-漏洞危害-测试方法(手工测试,工具测试)-靶场测试(分为PHP靶场、JAVA靶场、Python靶场基本上三种靶场全部涵盖)-实战演练(主要选择相应CMS或者是Vulnhub进行实战演练),如果对大家有帮助请Star鼓励我们创作更好文章。如果你愿意加入我们,一起完善这个项目,欢迎通过邮件形式(sec-redclub@qq.com)联系我们。
红日安全
2020/02/20
2.2K0
PHP 常见漏洞代码总结
只验证MIME类型: 代码中验证了上传的MIME类型,绕过方式使用Burp抓包,将上传的一句话小马*.php中的Content-Type:application/php,修改成Content-Type: image/png然后上传.
王 瑞
2022/12/28
1.4K0
实战 | 文件上传漏洞之最全代码检测绕过总结
文件上传漏洞是指攻击者上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务端命令的能力。该漏洞在业务应用系统中出现概率较高,究其原因是业务场景中上传附件、头像等功能非常常见,若在系统设计中忽略了相关的安全检查,则容易导致文件上传漏洞。
HACK学习
2022/02/17
15.5K1
实战 | 文件上传漏洞之最全代码检测绕过总结
基于纯真本地数据库的 IP 地址查询 PHP 源码
很多第三方的 IP 地址查询 API 接口,直接调用第三方的接口很方便,但也容易失效导致无法使用。因此今天来分享一个基于本地数据库的 IP 地址查询源码(亲测可行)!
码农编程进阶笔记
2022/09/27
2.7K0
基于纯真本地数据库的 IP 地址查询 PHP 源码
Flask 实现文件上传下载
Flask 针对文件的上传下载相关代码片段,多种方法,包括限制文件格式,大小等。 实现图片文件上传 # name: 简单的实现文件上传任务. import os from flask import Flask, request, url_for, send_from_directory from werkzeug import secure_filename ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif']) app = Flask(__nam
王 瑞
2022/12/28
1.2K0
PHP 字符串与文件操作
字符串比较(字节序): 字节序比较可以使用strcmp/strcasecmp两个函数,只需传入两个字符串即可.
王 瑞
2022/12/28
8850
php实现文件上传
存档: upload1.html(单文件上传) 1 <html> 2 <head> 3 <title>单个文件上传</title> 4 </head> 5 <body> 6 <form action="upload.php" method="post" enctype="multipart/form-data"> 7 <input type="hidden" name="MAX_FILE_SIZE" value="
Angel_Kitty
2018/04/08
4.2K0
php实现文件上传
php通过文件头检测文件类型通用类(zip,rar…)
首先说明下,上面文件头与文件类型映射关系来自网上,如果你有新的文件需要检查,只需要将映射加入即可。 如果你需要知道文件头信息,可以通过工具:winhex打开标准文件查找。如:
IT工作者
2023/07/21
4090
phpstudy后门文件分析以及检测脚本
2019.9.20得知非官网的一些下载站中的phpstudy版本存在后门文件,基于研究的目的,于是有了以下这文。
ChaMd5安全团队
2019/09/25
1K0
phpstudy后门文件分析以及检测脚本
类库封装-PHP图片处理工具
Base64生成图片文件,自动解析格式 /** * @desc Base64生成图片文件,自动解析格式 * @param $base64 可以转成图片的base64字符串 * @param $path 绝对路径 * @param $filename 生成的文件名 * @return array 返回的数据,当返回status==1时,代表base64生成图片成功,其他则表示失败 */ public function base64ToImag
程序猿的栖息地
2022/04/29
7650
PHP使用curl上传文件到远程服务器接口
笔者个人博客 https://qiucode.cn 欢迎大伙围观哦! 当然你的php.ini开启了curl扩展功能 1、文件上传 /** * 以文件上传 第二种方法 */ public function upload(){ $result = array('code' => 0, 'message' => 'ok'); ini_set('upload_max_filesize', '20M'); ini_set('po
游离于山间之上的Java爱好者
2022/12/18
1.8K0
推荐阅读
相关推荐
php判断文件上传图片格式的实例详解
更多 >
LV.1
这个人很懒,什么都没有留下~
目录
  • Security 权限控制
  • 一、注解权限控制
    • 1.1 启用注解配置
    • 1.2 设置用户角色权限
      • 角色
      • 权限
    • 1.3 获取用户信息
    • 1.4 在方法上添加注解
      • securedEnabled
      • jsr250Enabled
      • prePostEnabled
  • 二、RBAC权限控制
    • 2.1 创建校验类
    • 2.2 添加自定义的权限表达式
  • 三、支持跨域请求
    • 3.1 添加跨域请求配置
    • 3.2 修改配置支持跨域请求
    • 3.3 修改VUE携带验证信息
  • 四、设置权限不足异常
    • 4.1 添加异常处理类
    • 4.2 配置异常处理
    • 4.3 配置登录异常处理
  • 五、表结构
  • 六、前后端分离
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档