栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Boot 之 Spring Security高级配置(权限和资源的关系)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Boot 之 Spring Security高级配置(权限和资源的关系)

Spring Security高级配置(权限和资源的关系) 角色继承

Spring Security中经常有多个角色,角色之间应该有一定关系,一般来说角色之间是有关系的,例如ROLE_admin一般既具有admin的权限,又具有user的权限。那么如何配置这种角色继承关系呢?在Spring Security 中只需要开发者提供一 个RoleHierarchy 即可。假设ROLE_dba 是终极大Boss,具有所有的权限,ROLE_admin 具有ROLE_user的权限,ROLE_ user 则是一个公共角色,即ROLE_admin继承ROLE_user、ROLE_dba继承ROLE_ admin ,要描述这种继承关系,只需要开发者在SpringSecurity的配置类中提供一个RoleHierarchy即可,代码如下:

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;
    
	//这是增加的部分
    @Bean
    RoleHierarchy roleHierarchy(){
        RoleHierarchyImpl roleHierarchy=new RoleHierarchyImpl();
        String hierarchy="Role_dba>Role_admin>Role_user";
        roleHierarchy.setHierarchy(hierarchy);
        return roleHierarchy;
    }

    @Bean
    public static PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(10);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin*.xml
            
        
        
            src/main/resources
            
                **/*
            
        
    

3. 配置数据库

在application.properties中进行数据库连接配置:

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://120.55.61.170:3306/fristweb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=fristweb
spring.datasource.password=dTNFJW4B5MrwT4KS
spring.datasource.initialSize= 5
spring.datasource.minIdle=5
spring.datasource.maxActive= 20
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECt 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true

mybatis.type-aliases-package=suohechuan.testforever.model
mybatis.mapper-locations=classpath:mapper/*.xml
4. 创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Role {
    private Integer id;
    private String name;
    private String nameZh;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enable;
    private Boolean locked;
    private List roles;

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public String getPassword() {
        return password;
    }


    @Override
    public Collection getAuthorities() {
        List authorities = new ArrayList<>();
        for (Role role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return !locked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return enable;
    }

}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Menu {
    private Integer id;
    private String pattern;
    private List roles;
}
5. 创建UserService

接下来创建UserService,代码如下:

@Service
public class UserService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.loadUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("账户不存在!");
        }
        user.setRoles(userMapper.getUserRolesByUid(user.getId()));
        return user;
    }
}

代码解释:

  • 定义UserService实现UserDetailService接口,并实现该接口中的loadUserByUsername方法,该方法的参数就是用户登录时输入的用户名,通过用户名去数据库中查找用户,如果没有查找到用户,就抛出一个账户不存在的异常,如果查找到了用户,就继续查找该用户所具有的角色信息,并将获取到的user对象返回,再由系统提供的DaoAuthenticationProvider类去比对密码是否正确。
  • loadUserByUsername 方法将在用户登录时自动调用。

当然,这里还涉及UserMapper和UserMapper.xml,相关源码如下:

@Mapper
public interface UserMapper {
    User loadUserByUsername(String username);

    List getUserRolesByUid(Integer id);
}




    
        select *
        from user
        where username = #{username}
    
    

8. 配置 Spring Security

这里与前文的配置相比,主要是修改了 configure(HttpSecurity http) 方法的实现并添加了两个 Bean。至此我们边实现了动态权限配置,权限和资源的关系可以在 menu_role 表中动态调整。

@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;
 
    // 指定密码的加密方式
    @SuppressWarnings("deprecation")
    @Bean
    PasswordEncoder passwordEncoder(){
        // 使用BCrypt进行加密
        return new BCryptPasswordEncoder(10);
    }
 
    // 配置用户及其对应的角色
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }
 
    // 配置 URL 访问权限
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor() {
                    @Override
                    public  O postProcess(O object) {
                        object.setSecurityMetadataSource(cfisms());
                        object.setAccessDecisionManager(cadm());
                        return object;
                    }
                })
                .and().formLogin().loginProcessingUrl("/login").permitAll()//开启表单登录并配置登录接口
                .and().csrf().disable(); // 关闭csrf
    }
 
    @Bean
    CustomFilterInvocationSecurityMetadataSource cfisms() {
        return new CustomFilterInvocationSecurityMetadataSource();
    }
 
    @Bean
    CustomAccessDecisionManager cadm() {
        return new CustomAccessDecisionManager();
    }
}

代码解释:

  • 本案例 WebSecurityConfig类的定义是对10.2节中WebSecurityConfig定义的补充,主要是修改了configure(HttpSecurity htp)方法的实现并添加了两个Bean。
  • 第9、10行,在定义FilterSecurityInterceptor时,将我们自定义的两个实例设置进去即可。

配置完成后,接下来就可以创建Controller进行测试了,测试方式与Security上节致,这里不再赘述。

@RestController
public class HelloController {
    @GetMapping("/admin/hello")

    public String admin() {
        return "hello admin!";
    }

    @GetMapping("/user/hello")
    public String user() {
        return "hello user! ";
    }

    @GetMapping(" /db/hello")
    public String dba() {
        return "hello dba!";
    }

    @GetMapping("/hello")
    public String hello() {
        return "hello!";
    }
}

经过上面的配置,我们已经实现了动态配置权限,权限和资源的关系可以在menu_ role 表中动态调整。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/876911.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号