Spring Security授权方法
admin
2023-02-13 14:20:00
0次

授权的方式包括web授权和方法授权,web授权是通过url拦截进行授权,方法授权是通过方法拦截进行授权,他们都会调用accessDecisionManager进行授权决策,若为web授权则拦截器为:FilterSecurityIntecepter,若为方法授权则拦截器为:MethodSecurityIntecepter,如果同时通过web授权和方法授权则先进行web授权再执行方法授权,最后决策通过,则允许访问资源,否则将禁止访问。

1.       准备环境

在user_dbs数据库中创建表:

角色表:

CREATE TABLE t_role (

id VARCHAR(32) NOT NULL,

role_name VARCHAR(255) DEFAULT NULL,

description VARCHAR(255) DEFAULT NULL,

create_time DATETIME DEFAULT NULL,

update_time DATETIME DEFAULT NULL,

STATUS CHAR(1) NOT NULL,

PRIMARY KEY (id),

UNIQUE KEY unique_role_name (role_name)

) ENGINE=INNODB DEFAULT CHARSET=utf8

 

INSERT INTO t_role(id,role_name,description,create_time,update_time,STATUS) VALUES ('1','管理员',NULL,NULL,NULL,'');

 

用户角色表:

CREATE TABLE `t_user_role` (

`user_id` VARCHAR(32) NOT NULL,

`role_id` VARCHAR(32) NOT NULL,

`create_time` DATETIME DEFAULT NULL,

`creator` VARCHAR(255) DEFAULT NULL,

PRIMARY KEY (`user_id`,`role_id`)

) ENGINE=INNODB DEFAULT CHARSET=utf8

 

INSERT INTO `t_user_role`(`user_id`,`role_id`,`create_time`,`creator`) VALUES

('1','1',NULL,NULL);

 

 

 

权限表:

CREATE TABLE `t_permission` (

`id` VARCHAR(32) NOT NULL,

`code` VARCHAR(32) NOT NULL COMMENT '权限标识符',

`description` VARCHAR(64) DEFAULT NULL COMMENT '描述',

`url` VARCHAR(128) DEFAULT NULL COMMENT '请求地址',

PRIMARY KEY (`id`)

) ENGINE=INNODB DEFAULT CHARSET=utf8

 

INSERT INTO `t_permission`(`id`,`code`,`description`,`url`) VALUES ('1','p1','测试资源

1','/r/r1'),('2','p3','测试资源2','/r/r2');

 

角色权限关系表:

CREATE TABLE `t_role_permission` (

`role_id` VARCHAR(32) NOT NULL,

`permission_id` VARCHAR(32) NOT NULL,

PRIMARY KEY (`role_id`,`permission_id`)

) ENGINE=INNODB DEFAULT CHARSET=utf8

 

INSERT INTO `t_role_permission`(`role_id`,`permission_id`) VALUES ('1','1'),('1','2');

 

2.       修改UserDetailService

(1)    修改dao接口

List findPermissionsByUserId(String userId) {
     String sql = +
             +
             +
             +
             ;
     List list = .query(sql, Object[]{userId}, BeanPropertyRowMapper<>(PermissionDto.));
     List permissions = ArrayList<>();
     list.iterator().forEachRemaining(c-> .add(c.getCode()));
     permissions;
 }
 
     (2)修改UserDetailService
          
SpringDataUserDetailsService UserDetailsService {
     UserDao ;
     UserDetails loadUserByUsername(String username) UsernameNotFoundException {
         System..println(+username);
         UserDto user = .getUserByUsername(username);
         (user == ){
             ;
         }
         List permissions = .findPermissionsByUserId(user.getId());
         String[] perarray = String[permissions.size()];
         permissions.toArray(perarray);
         UserDetails userDetails =
                 User.(user.getFullname()).password(user.getPassword()).authorities(perarray).build();
         userDetails;
     }
 }

在前面的例子中我们完成了认证拦截,并对/r/**下的资源进行简单的保护,我们还可以通过给http.authorizeRequests()添加多个节点来进行灵活的授权控制

.authorizeRequests() ()
 .antMatchers().hasAuthority() ()
 .antMatchers().hasAuthority() ()
 .antMatchers().access() ()
 .antMatchers().authenticated() ()
 .anyRequest().permitAll() ()
 .and()
 .formLogin()

 

(1)http.authorizeRequests() 方法有多个子节点,每个macher按照他们的声明顺序执行

(2)指定”/r/r1”url拥有p1权限能够访问

(5)指定除了r1,r2,r3之外”/r/**”资源通过身份认证就可以访问

(6)其它的资源不做保护,可以任意访问

 

注意:规则的顺序,更具体的规则应该先写

例如:

.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/admin/login").permitAll()

第一条规则中已经规定以/admin开始的url需要具备ADMIN的角色才能访问,即使第二条规则中/admin/login这个url可以被访问在访问/admin/login时也需要具备ADMIN的角色,因为它在前面,第二条规则被忽略。

因此登录页面的规则应该放在前面

.antMatchers("/admin/login").permitAll()

.antMatchers("/admin/**").hasRole("ADMIN")
保护URL常用的方法有:

Authenticated()保护URL,需要用户登录

PermitAll()指定URL无需保护,一般用于静态资源文件

hasRole(String role)限制单个角色访问,角色将被增加”ROLE_”,所以”ADMIN”将和”ROLE_ADMIN”比较

hasAuthority(String authority)限制单个权限访问

hasAnyRole(String Roles…)允许多个角色访问

hasAnyyAuthority(String …Authorities)允许多个权限访问

access(String attribute)可以创建复杂的限制

hasIpAddress(String ipAddressExpression)限制ip地址或子网

 

 

方法授权:

从Spring Security2.0版开始支持服务层方法授权。

我们可以在任何@Configuration实例上使用@EnableGlobalMethodSecurity来启用基于注解的安全性,以下将启用Spring Security的 @Secured 注释

@Configuration
 @EnableGlobalMethodSecurity(securedEnabled = )
 WebSecurityConfig WebSecurityConfigurerAdapter {
…

}

然后向方法(类或接口)添加注解就会限制对该方法的访问。

例如:

BankService {
     @Secured()
     Account readAccount(Long id);
     @Secured()
     Account[] findAccounts();
     @Secured()
     Account post(Account account, amount);
 }
以上配置表明readAccount和findAccounts方法可以匿名访问
Post方法需要有TELLER角色才能访问
 
启用prePost注解
@Configuration
 @EnableGlobalMethodSecurity(prePostEnabled = )
 WebSecurityConfig WebSecurityConfigurerAdapter {
…

}

例如:
BankService {
     @PreAuthorize()
     Account readAccount(Long id);
     @PreAuthorize()
     Account[] findAccounts();
     @PreAuthorize()
     Account post(Account account, amount);
 }
以上配置表明readAccount和findAccounts可以匿名访问
Post方法需要同时拥有p_transfer和p_read_account权限才能访问


相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...