Spring Security相关图形

体系的组织结构设计(重要组件、模块划分、模块间交互)
常用工具 

一、需求调研、需求分析(即应用场景)

  1. spring security 是基于 spring 的安全框架,它提供全面的安全性解决方案

二、框架的设计思想

  1. 认证(你是谁,用户/设备/系统,是否合法)。
  2. 验证(你有干什么的权限,也叫权限控制/授权,允许执行的操作)。ds:这个验证可以控制到方法的级别,验证用户能做什么。

三、工作原理、运行流程

        文: 基于 Filter , Servlet, AOP 实现身份认证和权限验证。

四、详细设计:实现方法(技术)

  1. spring security同时在Web请求级和方法调用级处理身份确认和授权。
  2. spring security使用spring的IOC、AOP为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复 代码的工作。

        ds:aop做的是在你调用方法之前呢,使用面向切面编程实现验证功能。

        ds:引入的spring-security-web.jar包实现在web中实现验证的管理。

五、使用说明:常用配置

1、Using generated security password: 79e0d51a-03cf-4d46-abdd-6ba4c79d342c

        ds:当前在初步使用时, spring security给你生成的临时密码。用户是:user,密码是:79e0d51a-03cf-4d46-abdd-6ba4c79d342c,你现在使用user + 79e0d51a-03cf-4d46-abdd-6ba4c79d342c是可以访问系统的。

2、关闭验证

        //排除 Secuirty 的配置,让他不启用
        @SpringBootApplication(exclude = {SecurityAutoConfiguration.class})

3、java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

         spring security 5 版本要求密码比较加密,否则报错

六、具体1:例子1:临时、配置式的用户名和密码

1、默认用户名+临时密码

 注:如果消除浏览器缓存后再访问XxxController.java,还是要登录。

        ds:这个login登录窗口是spring security默认帮我们实现的登录窗口,只有用户名和密码正确才能访问XxxController.java中的方法。

        实现原理是,spring security在处理器XxxController.java中的方法的前面使用aop做了一个拦截,这个拦截使用的就是spring security框架实现的身份认证,如果用户正确才能访问处理器的处理方法。

2、自定义用户名和密码

application.yml(application.properties):
spring:
  security:
    user:
      name: wkcto
      password: wkcto

七、具体2:例子2:使用内存中的用户信息

package com.wkcto.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.crypto.password.PasswordEncoder;
//  1. @Configuration :表示当前类是一个配置类(相当于是 spring 的 xml 配置文件),在这个类方法的返回值是 java 对象,这些对象放入到 spring 容器中。 
//  2. @EnableWebSecurity:表示启用 spring security 安全框架的功能 
//  3. @Bean:把方法返回值的对象,放入到 spring 容器中。
@Configuration
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder pe = passwordEncoder();
        auth.inMemoryAuthentication().withUser("zhansan").password(pe.encode("3")).roles();
        auth.inMemoryAuthentication().withUser("lisi").password(pe.encode("4")).roles();
        auth.inMemoryAuthentication().withUser("wangwu").password(pe.encode("5")).roles();
    }
    //创建 PasawordEncoder 的实现类, 实现类是加密算法
    @Bean 
    public PasswordEncoder passwordEncoder(){
         return new BCryptPasswordEncoder();
    }
}

八、具体3:例子3:基于(内存中)角色 Role 的身份认证, 同一个用户可以有不同的角色。同时可以开启对方法级别的认证(ds:用户访问方法时,在方法之上提供认证功能;)。

1、第一步:设置用户的角色

        ds:继承WebSecurityConfigurerAdapter.java,可以实现/提供自定义的认证信息的配置类。我们通过覆盖相应的方法,来提供自定义的,关于用户呀、认证呀,角色等等配置信息。



//定义两个角色 normal(普通), admin(超级管理员)
auth.inMemoryAuthentication()
    .withUser("zhangsan")
    .password(pe.encode("123456"))
    .roles("normal");

auth.inMemoryAuthentication()
    .withUser("lisi")
    .password(pe.encode("123456"))
    .roles("normal");

auth.inMemoryAuthentication()
    .withUser("admin")
    .password(pe.encode("admin"))
    .roles("admin","normal");

2、第二步:告诉框架,启动角色的功能      

/**
 * @EnableGlobalMethodSecurity:启用方法级别的认证,即认证这个方法能不能被访问
 *      prePostEnabled:boolean 默认是false
 *          true:表示可以使用@PreAuthorize注解 和 @PostAuthorize
 * @PreAuthorize:放在方法之上,给方法提供认证功能,当前用户属于指定角色,认证才能成功才能执行方法
 * @PostAuthorize:放在方法之上,给方法提供认证功能,当前用户属于指定角色,认证才能成功才能执行方法
 */
@EnableGlobalMethodSecurity(prePostEnabled = true)

完整版本:

package com.wkcto.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @EnableGlobalMethodSecurity:启用方法级别的认证
 *      prePostEnabled:boolean 默认是false
 *          true:表示可以使用@PreAuthorize注解 和 @PostAuthorize
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    //在方法中配置 用户和密码的信息, 作为登录的数据
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder pe = passwordEncoder();

        //定义两个角色 normal(普通), admin(超级管理员)
        auth.inMemoryAuthentication()
                .withUser("zhangsan")
                .password(pe.encode("123456"))
                .roles("normal");

        auth.inMemoryAuthentication()
                .withUser("lisi")
                .password(pe.encode("123456"))
                .roles("normal");
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password(pe.encode("admin"))
                .roles("admin","normal");

    }

    //创建密码的加密类
    @Bean
    public PasswordEncoder passwordEncoder(){
        //创建PasawordEncoder的实现类, 实现类是加密算法
        return new BCryptPasswordEncoder();
    }

}

3、第三步:设置角色与方法的对应关系

package com.wkcto.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String sayHello(){
        return "使用内存中的用户信息";
    }

    //指定 normal 和admin 角色都可以访问的方法
    @RequestMapping("/helloUser")
    @PreAuthorize(value = "hasAnyRole('admin','normal')")
    public String helloCommonUser(){
        return "Hello 拥有normal, admin角色的用户";
    }

    //指定admin角色的访问方法
    @RequestMapping("/helloAdmin")
    @PreAuthorize("hasAnyRole('admin')")
    public String helloAdmin(){
        return "Hello admin角色的用户可以访问";
    }
}

4、第四步:测试说明

(1)第1步:访问:http://localhost:8080/helloUser,跳转到登录页面:http://localhost:8080/login

(2)第2步:普通用户(normal)和超级管理员(admin)都可以访问helloUser方法

(3)第3步:清除缓存(cookie等其它数据)

(4)第4步:只有超级管理员(admin)都可以访问helloAdmin方法

九、具体3:例子3:基于 jdbc 的用户认证。

1、第一步:有spring security 框架UserDetails接口

        在 spring security 框架对象中用户信息的表示类是 UserDetails。UserDetails 是一个接口,高度抽象的用户信息类(相当于项目中的 User 类)。

package org.springframework.security.core.userdetails;

import java.io.Serializable;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;

public interface UserDetails extends Serializable {
    //  用户的角色信息列表,是一个集合,因为一个用户是可以有多个角色的
    Collection<? extends GrantedAuthority> getAuthorities();
    //  获取用户名
    String getPassword();
    //  获取密码
    String getUsername();
    //  账号是否是过期的
    boolean isAccountNonExpired();
    //  账号是否是锁定的
    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();
    //  账号是否是启用的
    boolean isEnabled();
}

2、第二步:有spring security 框架User类实现了UserDetails接口

        ds:我们可以创建User.java类的一个对象,来代表用来认证的用户信息,用来提供身价认证的数据。 spring security 框架底层会调用User.java对象,来进行用户身份的认证的。

        因此,我们需要做的是去创建这个User.java对象,封装此用户的:用户名、密码、角色集合,这3个用户信息就可以了。

        文档:需要向 spring security 提供 User 对象, 这个对象的数据来自数据库的查询。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.security.core.userdetails;

public class User implements UserDetails, CredentialsContainer {
    private static final long serialVersionUID = 500L;
    private static final Log logger = LogFactory.getLog(User.class);
    private String password;
    private final String username;
    private final Set<GrantedAuthority> authorities;
    private final boolean accountNonExpired;
    private final boolean accountNonLocked;
    private final boolean credentialsNonExpired;
    private final boolean enabled;
    
    //  username:用户名
    //  password:密码
    //  authorities:角色的集合
    public User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this(username, password, true, true, true, true, authorities);
    }

    public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
        if (username != null && !"".equals(username) && password != null) {
            this.username = username;
            this.password = password;
            this.enabled = enabled;
            this.accountNonExpired = accountNonExpired;
            this.credentialsNonExpired = credentialsNonExpired;
            this.accountNonLocked = accountNonLocked;
            this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
        } else {
            throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
        }
    }

    ......
}

3、第三步:实现 UserDetailsService 接口(怎么获取到User对象?怎么去查询数据库呢?)

package org.springframework.security.core.userdetails;

public interface UserDetailsService {
    //  参数:var1:传递参数userName
    //  返回值:UserDetails,security框架就是用这个对象来认证用户的。
    /*
     *  我们可以在loadUserByUsername()中去访问数据库,来获取到我们需要的用户信息。
     */
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}

重写方法 UserDetails loadUserByUsername(String var1) 在方法中获取数据库中的用户信息, 也就是执行数据库的查询,条件是用户名称。

        ds:Spring Security框架会自动检测到我们MyUserDetailService.java实现了UserDetailsService 接口,因此Spring Security框架底层就会自动调用loadUserByUsername()方法,其中会调用dao获取数据库中用户的数据信息(用户名、密码、角色),并返回UserDetails接口的实现User.java对象。由User对象提供了,用户名、密码、角色这些认证信息。

package com.wkcto.provider;

import com.wkcto.dao.UserInfoDao;
import com.wkcto.entity.UserInfo;
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.User;
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("MyUserDetailService")
public class MyUserDetailService implements UserDetailsService {

    @Autowired
    private UserInfoDao dao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = null;
        UserInfo userinfo = null;
        if( username != null){
            userinfo = dao.findByUsername(username);

            if( userinfo != null){
                List<GrantedAuthority> list = new ArrayList<>();

                //角色必须以ROLE_开头(规则:必须有此前缀)
                GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" +userinfo.getRole());
                list.add(authority);

                //创建User对象
                user = new User(userinfo.getUsername(),userinfo.getPassword(),list);
            }

        }
        return user;
    }
}

4、第四步:重写自定义配置类MyWebSecurityConfig.java

package com.wkcto.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("MyUserDetailService")
    private UserDetailsService userDetailsService;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //  auth:验证器
        //  auth.userDetailsService()方法需要传入一个UserDetailsService的实例做为参数。
        //  .passwordEncoder( new BCryptPasswordEncoder())表明使用的密码加密方式是BCryptPasswordEncoder,这个也是我们常用的方式
        auth.userDetailsService(userDetailsService).passwordEncoder( new BCryptPasswordEncoder());
    }
}

5、第五步:XxxControler类

package com.wkcto.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String sayHello(){
        return "使用内存中的用户信息";
    }

    //指定 normal 和admin 角色都可以访问的方法
    @RequestMapping("/helloUser")
    @PreAuthorize(value = "hasAnyRole('admin','normal')")
    public String helloCommonUser(){
        return "===Hello 拥有normal, admin角色的用户===";
    }

    //指定admin角色的访问方法
    @RequestMapping("/helloAdmin")
    @PreAuthorize("hasAnyRole('admin')")
    public String helloAdmin(){
        return "===Hello admin角色的用户可以访问==";
    }
}

6、第六步:测试

附1、pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.wkcto</groupId>
  <artifactId>ch04-jdbc</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>


  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <!--加入spring boot -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-parent</artifactId>
    <version>2.0.6.RELEASE</version>
  </parent>

  <!--指定依赖-->
  <dependencies>
    <!--web开发相关依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--spring security项目的起步依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>
    <!--数据库访问框架jpa-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

附2、UserInfo.java用户信息表

package com.wkcto.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

//  jpa中定义的一个注解
//  表示当前类是一个实体类, 表示数据库中的一个表
//  表名默认和类名一样的
@Entity
public class UserInfo {
    //  用户id
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    //  用户名称
    private String username;
    //  密码
    private String password;
    //  角色
    private String role;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

附3、dao层

package com.wkcto.dao;

import com.wkcto.entity.UserInfo;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * JpaRepository<UserInfo,Long>
 *     泛型UserInfo:用户信息实体类
 *     Long:主键是Long类型的
 *
 * UserInfoDao继承了JpaRepository,这样我们就有一个访问数据库的这么一个类了,叫做UserInfoDao
 */
public interface UserInfoDao extends JpaRepository<UserInfo,Long> {
    //按照username查询数据库信息
    UserInfo findByUsername(String username);
}

附4、service层

package com.wkcto.service;

import com.wkcto.entity.UserInfo;

public interface UserInfoService {
    UserInfo findUserInfo(String username);
}
package com.wkcto.service.impl;

import com.wkcto.dao.UserInfoDao;
import com.wkcto.entity.UserInfo;
import com.wkcto.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoDao dao;
    @Override
    public UserInfo findUserInfo(String username) {
        UserInfo userinfo = dao.findByUsername(username);
        return userinfo;
    }
}

附5、application.properties

spring.datasource.url=jdbc:mysql:///mysql?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#  DDL生成
spring.jpa.generate-ddl=true
#  显示sql
spring.jpa.show-sql=true
#  使用的数据库mysql
spring.jpa.database=mysql

附6、主启动类JdbcApplication.java

package com.wkcto;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JdbcApplication {


    public static void main(String[] args) {
        SpringApplication.run(JdbcApplication.class,args);
    }
}

附7、数据库初始化类JdbcInit.java

package com.wkcto.init;

import com.wkcto.dao.UserInfoDao;
import com.wkcto.entity.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

//  注入到容器中(数据库初始化完成后注释掉)
@Component
public class JdbcInit {
    //  注入dao
    @Autowired
    private UserInfoDao dao;

    //  对象创建之后呢,来执行这个方法(数据库初始化完成后注释掉)
    @PostConstruct
    public void init(){
        //  spring security加密功能
        PasswordEncoder encoder = new BCryptPasswordEncoder();
        UserInfo u  = new UserInfo();
        u.setUsername("zhangsan");
        u.setPassword(encoder.encode("123456"));
        u.setRole("normal");
        dao.save(u);

        u = new UserInfo();
        u.setUsername("admin");
        u.setPassword(encoder.encode("admin"));
        u.setRole("admin");
        dao.save(u);
    }
}

初始化数据效果,如下图:

十、其它具体

1、Spring Security与Spring的关系

        ds:Spring Security是完全基于spring框架的。在 Spring Framework 基础 上,spring security 充分利用了依赖注入(DI)和面向切面编程(AOP)功能,为 应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。 

2、Spring Security与Spring MVC的关系

        文:是一个轻量级的安全框架。它与 Spring MVC 有很好地集成。

3、Spring Security是否可以单独使用?

        ds:Spring Security也可以单独使用,来完成身份认证以及权限认证功能。

4、概念:认证与授权

  1. authentication:认证, 认证访问者是谁。 一个用户或者一个其他系统是不是当前要访问的系统中的有效用户。认证完成以后,仅确定此用户/系统是有效用户,但是它具体能干什么,还要看授权情况。
  2. authorization:授权, 访问者能做什么,对系统中的资源能做哪些操作(复制、粘贴、访问Controller的方法等)
        比如说张三用户要访问一个公司 oa 系统。
        首先系统要判断张三是不是公司中的有效用户。 认证张三是不是有效的用户,是不是公司的职员。
        其次,授权: 判断张三能否做某些操作, 如果张三是个领导可以批准下级的请假, 其他的操作。 如果张三只是一个普通用户,只能看自己的相关数据, 只能提交请假申请等等。

5、RBAC模型

        ds:在做认证和授权中,我们主要采用的模型是RBAC模型。RBAC模型是在做权限控制中,应用得非常广泛的模型。

        RBAC 是基于角色的访问控制( Role角色-Based Access Control访问控制  ) 在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户。用户属于某个角色,就拥有了对应的权限。这样的权限 设计很清楚,管理起来很方便。
        权限:能对资源的操作, 比如增加,修改,删除,查看等等。
        角色:自定义的, 表示权限的集合。一个角色可以有多个权限。
        ds:Role角色是我们开发过程中,需要自己去设计的、自定义的。其中Role角色,代表的是某些权限的集合。通过Role角色来判断,当前用户是否能够对系统中的资源进行访问。
        权限,即能够对系统中的资源做什么操作,这就是权限。资源包括,用户的用户各种操作、数据库数据的访问、文件CRUD操作等。
        其基本思想是,对系统操作的各种权限不是直接授予具体的用户,而是在用户集合与权限集合之间建立一个角色集合,把权限授予/赋给角色。每一种角色对应一组相应的权限。一旦用户被分配了适当的角色后,该用户就拥有此角色的所有操作权限。这样做的好处是,不必在每次创建用户时都进行分配权限的操作,只要分配用户相应的角色即可,而且角色的权限变更比用户的权限变更要少得多,这样将简化用户的权限管理, 减少系统的开销。
RBAC : 用户是属于角色的, 角色拥有权限的集合。 用户属于某个角色, 他就具有角色对应的权限。
       
设计案例:
  1. 系统中有张三,李四,他们是普通员工,只能查看数据。
  2. 系统中经理,副经理他们能修改数据。

设计过程: 

        第一步:设计有权限的集合:

                经理角色,具有修改数据的权限,删除,查看等等。

                普通用户角色: 只读角色,只能看数据 ,不能修改,删除。
        第二步:
                让张三,李四是只读的,普通用户角色。
                让经理,副经理他们都是经理角色。
        第三步:
                公司以后增加新的普通员工,加入到“普通用户角色”就可以了,不需要在增加新的角色。

                公司增加经理了, 只要加入到“经理角色”就可以了。

RBAC 设计中的表:

  1. 用户表: 用户认证(登录用到的表),包含字段一般为:用户名,密码,是否启用,是否锁定等信息。
  2. 角色表:定义角色信息,包含字段一般是:角色名称, 角色的描述。
  3. 用户和角色的关系表: 用户和角色是多对多的关系。 一个用户可以有多个角色, 一个角色可以有多个用户。
  4. 权限表, 用于存储角色可以有哪些权限。
  5. 角色和权限的关系表,属于有业务需求时扩展的表。

        ds:RBAC权限控制功能模块,应该是像AOP的切面一样,可以单独存在的,可以反复使用,即可以像切面一样切入需要做权限控制的地方。可以使用在多个系统中,可以单独进行维护和管理的。 

        而spring security框架,就是可以独立开于我们的系统,来进行权限的控制和管理的框架(系统)。

4、spring specurity中认证的接口和类

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值