SpringBoot集成SpringSecurity(入门级)

简介: 目录Springboot集成SpringSecurity Demo 快速上手-初步入门: 创建单用户单角色的安全控制多用户多角色的实现思路 每个身份都使用一个登录实体类...

目录

目录创建于2017-12-18


Springboot集成SpringSecurity

Demo

快速上手-初步入门:

创建单用户单角色的安全控制

  • 添加依赖
   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
      @Autowired
      private ReaderRepository readerRepository;
      @Override
      protected void configure(HttpSecurity http) throws Exception {
        http
          .authorizeRequests()
            .antMatchers("/").access("hasRole('READER')")//要求登陆者进入根目录必须具有 READER 的角色
            .antMatchers("/**").permitAll()//其他页面开放了权限
          .and()
          .formLogin()
            .loginPage("/login")//登录表单的路径
            .failureUrl("/login?error=true");
      }
      @Override
      protected void configure(
                  AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new UserDetailsService() {//定义自定义的UserDetailService
            @Override
            public UserDetails loadUserByUsername(String username)
                throws UsernameNotFoundException {
              UserDetails userDetails = readerRepository.findOne(username);
              if (userDetails != null) {
                return userDetails;
              }
              throw new UsernameNotFoundException("User '" + username + "' not found.");
            }
          });
      }
    }

Repository类

   public interface ReaderRepository extends JpaRepository<Reader, String> {}
    //登录实体类
    @Entity
    public class Reader implements UserDetails {
      private static final long serialVersionUID = 1L;
      @Id
      private String username;
      private String fullname;
      private String password;
      //省略setget
      //授予READER权限
      @Override
      public Collection<? extends GrantedAuthority> getAuthorities() {
        return Arrays.asList(new SimpleGrantedAuthority("ROLE_READER"));
      }
      //不过期
      @Override
      public boolean isAccountNonExpired() { return true;}
      //不加锁
      @Override
      public boolean isAccountNonLocked() {return true;}
      //不禁用
      @Override
      public boolean isCredentialsNonExpired() {return true;}
      //可用
      @Override
      public boolean isEnabled() { return true;}
    }

多用户多角色的实现思路

  • 使用多个实体类(实现了UserDetails接口),一个权限类,再一个多对多连接,就得到了多用户,多权限的控制
  • 在页面上加上角色的判断来控制数据显示,业务操作等功能

  • 根据书上案例代码,可以得出结论,用户表,角色表,用户角色关联表,用户表是可以多张的,角色公用一张即可,然后关联表也对应的多张,就能实现具体的业务需求

    • 例如:一个网上在线阅读书城,作家和读者以及编辑,网站后台管理员等角色的不同权限对应的页面甚至页面上细分的各个模块
  • Author Admin Reader 三个类
    继承了UserDetails接口的实体类的配置

    //配置多对多的关系,用户和角色(权限)之间的关系,是通用的改下属性名即可
    @ManyToMany(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER)
    private List<AllRoles> roles ;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
        List<AllRoles> roles = this.getRoles();
        for(AllRoles role:roles){
            auths.add(new SimpleGrantedAuthority(role.getRole_name()));
        }
        return auths;
    }
    // 登录的用户名,如果属性不是叫username,就要重写,返回应该的用户名属性就是了
    @Override
    public String getUsername() { return this.reader_name;}
    @Override
    public boolean isAccountNonExpired() {return true;}
    @Override
    public boolean isAccountNonLocked() {return true;}
    @Override
    public boolean isCredentialsNonExpired() {return true;}
    @Override
    public boolean isEnabled() {return true;}
每个身份都使用一个登录实体类
  • 然后使用不同的dao层查询,显然的实体类登录查询的效率及其低且不易扩展
  • 设置好spirng.jpa.hibernate.ddl-auto=update
  • 第一次运行还会有没有实体对应的表这样的提示,说明了他正在根据多对多映射创建实体表,也体现了这个多种用户模式下需要实体等量的连接表
  • 所以这个是要查询多张表了
    • (除非UserDetailService接口的loadUserByUsername能收到表类别的参数)
    • 也可以考虑使用一个字符串,然后用特殊字符把类型放进去,然后正则取出来
    • 登录页面就需要自定义一个函数进行拼接(或者使用校验来拼接?)
另一种思路:
  • 使用一个登录用户表(序列id,用户名,密码,用户编码(对应多张表))
  • 角色表(序列id,用户编码,角色)
    这样的话扩展就只要加表,使用同一个主键生成策略就可以了

  • 思考:

    • 其实这个安全框架使用的是角色控制,而不是权限控制,目前的了解,达不到Oracle那样的权限加角色控制

实现细节

关于注解的几种使用方式

@Secured

  • 这是基于Spring特定的注解

@RolesAllowed

  • JSR-250的@RolesAllowed Java标准定义的注解,与上面的注解是差不多的
  • 但是都是有局限性,只能判断请求是否有权限,不能进行更多的自定义判断

SpringSecurity3.0 开始提供了 SpEL表达式

需要先配置这个配置类,后面的注解才会生效

    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration{}
  • @PreAuthorize 方法调用前,基于表达式的计算结果来限制方法的访问
  • @PostAuthorize 允许方法调用,如果表达式是false 抛出安全异常
  • @PostFilter 允许方法调用,按照表达式来过滤方法的结果
  • @PreFilter 允许方法调用,必须进入方法前过滤输入值

  • 方法调用前验证权限,示例:

    • @PreAuthorize("hasRole('ROLE_ADMIN')") 只允许该权限的用户访问
    • 方法入参user,限定读者用户的text长度小于140,或者是作家用户无限制
    • @PreAuthorize("(hasRole('ROLE_READER') and #user.text.length()<=140 ) or hasRole('ROLE_AUTHOR')")
  • 方法调用之后验证权限,示例;
    • @PostAuthorize("returnObject.spitter.username == principal.username")
    • public Spittle getSpittleById(long id){}
    • 保护方法,只有当返回的对象就是当前登录的用户时,才返回,不然抛出安全异常
      以上是保护方法的调用,但是有时候保护的是数据的输入输出:
  • 过滤方法的输入输出
    • 事后对方法的返回值进行过滤
      • @PreAuthorize("hasAnyRole({'ROLE_ADMIN','ROLE_USER'})")
      • @PostFilter("hasRole('ROLE_ADMIN') || filterObject.user.username == principal.name")
      • public List<User> getUsers(){}
      • 该示例就是限制了如果是管理员可以获取到所有数据,普通用户只能看到自己
      • 但是这种实现是不好的,只是一个例子,只获取自己,重载方法加个id参数就好了,上面的实现,把数据全拿出来再判断,性能上。。。
    • 事先对方法的参数进行过滤
      • @PreAuthorize("hasAnyRole({'ROLE_ADMIN','ROLE_USER'})")
      • @PreFilter("hasRole('ROLE_ADMIN') || targetObject.user.username == principal.name")
      • public void deleteUsers(){List<User> users}
      • 示例实现了传入一个集合,要删除的用户,但是当前用户只能删除自己,管理员才能删除集合里所有的用户
    • 定义许可计算器
      • @PreFilter("hasPermission(targetObject,'delete')") 用户是否有权限删除目标对象?
      • 使用了自定义的计算器类来实现这个判断,表达式简洁,但是自定义类不好写
      • 实现PermissionEvaluator接口,新建hasPermission方法,功能就是判断是否有权限,其实就是对比目标对象是不是当前用户
      • 创建好类后,重载GlobalMethodSecurityConfiguration配置类的createExpressionHalder方法,注册进去
      • DefaultMethodSecurityExperssionHandler ex = new De...();
      • ex.setPermissionEvaluator(new 自定义类);
      • return ex;

保护方法应用

  • @Secured 注解限制方法调用
目录
相关文章
|
2月前
|
安全 Java 数据库
SpringSecurity认证授权及项目集成
本文介绍了基于Spring Security的权限管理框架,涵盖认证、授权与鉴权核心概念,通过快速入门示例演示集成流程,并结合数据库实现用户认证。进一步扩展实现正常登录,JWT登录及鉴权管理器,实现灵活的安全控制,适用于前后端分离项目中的权限设计与实践。
260 4
|
8月前
|
安全 Java Apache
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
443 0
|
8月前
|
安全 Java 数据安全/隐私保护
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
330 0
|
5月前
|
前端开发
SpringBoot2.3.1集成Knife4j接口文档
SpringBoot2.3.1集成Knife4j接口文档
562 44
|
4月前
|
JSON 分布式计算 大数据
springboot项目集成大数据第三方dolphinscheduler调度器
springboot项目集成大数据第三方dolphinscheduler调度器
272 3
|
4月前
|
缓存 JSON 前端开发
第07课:Spring Boot集成Thymeleaf模板引擎
第07课:Spring Boot集成Thymeleaf模板引擎
515 0
第07课:Spring Boot集成Thymeleaf模板引擎
|
4月前
|
Java 关系型数据库 MySQL
springboot项目集成dolphinscheduler调度器 实现datax数据同步任务
springboot项目集成dolphinscheduler调度器 实现datax数据同步任务
570 2
|
4月前
|
分布式计算 Java 大数据
springboot项目集成dolphinscheduler调度器 可拖拽spark任务管理
springboot项目集成dolphinscheduler调度器 可拖拽spark任务管理
292 2
|
分布式计算 大数据 Java
springboot项目集成大数据第三方dolphinscheduler调度器 执行/停止任务
springboot项目集成大数据第三方dolphinscheduler调度器 执行/停止任务
89 0
下一篇
oss云网关配置