1.rbac

本文介绍了基于角色的访问控制(RBAC)模型,详细阐述了RBAC在组织中的应用,以及权限和角色的操作,包括权限注解和相关服务接口。此外,还提及了登录过程与登录控制器以及安全控制拦截器的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.基于角色的权限管理

访问控制策略一般有以下几种方式:

  1. 自主型访问控制(DAC):用户/对象来决定访问权限。信息的所有者来设定谁有权限来访问信息以及操作类型(读、写、执行。。。)。是一种基于身份的访问控制。例如UNIX权限管理。
  2. 强制性访问控制(MAC):系统来决定访问权限。安全属性是强制型的规定,它由安全管理员或操作系统根据限定的规则确定的,是一种规则的访问控制。
  3. 基于角色的访问控制(RBAC):角色决定访问权限。用组织角色来同意或拒绝访问。比MAC、DAC更灵活,适合作为大多数公司的安全策略,但对一些机密性高的政府系统不适用。
    Role-Based Access Control
  4. 规则驱动的基于角色的访问控制:提供了一种基于约束的访问控制,用一种灵活的规则描述语言和一种ixn的信任规则执行机制来实现。
  5. 基于属性证书的访问控制:访问权限信息存放在用户属性证书的权限属性中,每个权限属性描述了一个或多个用户的访问权限。但用户对某一资源提出访问请求时,系统根据用户的属性证书中的权限来判断是否允许或拒绝;

RBAC(Role-Based Access Control)

基于角色的访问控制,模型是20世纪90年代研究出来的一种新模型,但从本质上讲,这种模型是对前面描述的访问矩阵模型的扩展。这种模型的基本概念是把许可权(Permission)与角色(Role)联系在一起,用户通过充当合适角色的成员而获得该角色的许可权。
在实际的组织中,为了完成组织的业务工作,需要在组织内部设置不同的职位,职位既表示一种业务分工,又表示一种责任与权利。根据业务分工的需要,职位被划分给不同群体,各个群体的人根据其工作任务的需要被赋予不同的职责和权利,每个人有权了解与使用与自己任务相关的信息与资源,对于那些不应该被知道的信息则应该限制他们访问。这就产生了访问控制的需求。

例如,在一个大学中,有校长、副校长、训练部长、组织处长、科研处长、教保处长等不同的职位,在通常情况下,职位所赋予的权利是不变的,但在某个职位上工作的人可以根据需要调整。RBAC模型对组织内部的这些关系与访问控制要求给出了非常恰当的描述。

二.权限和角色的操作

权限注解

RequiredPermission

//该注解贴在哪个方法上就表示该方法 需要权限才能访问
@Retention(RetentionPolicy.RUNTIME)//注解可以加载到JVM中
@Target(ElementType.METHOD)//注解可以贴在方法上
public @interface RequiredPermission {
    String value();//描述权限的名称
}

在Controller中的方法,贴上注解,表示该方法需要权限访问

@RequiredPermission("编辑员工")
    @RequestMapping("input")
    public String input(Long id,Model model){
        if (id != null) {
            Employee employee = employeeService.get(id);
            System.out.println("------>>>>>>: "+employee);
            model.addAttribute(employee);
        }
        model.addAttribute("depts",departmentService.list());
        model.addAttribute("roles", roleService.list());
        return "employee/input";
    }

加载权限的方法,保存数据

DpartementServiceImple

public void reload() {
        //先查询数据库中已有的权限表达式
        List<String> exprs = permissionMapper.selectAllExpressions();
        //1. 从容器获取所有的Controller对象
        Collection<?> beans = ctx.getBeansWithAnnotation(Controller.class).values();
        for (Object ctrl : beans) {
            //2. 获取Controller中所有的方法对象
            Method[] methods = ctrl.getClass().getDeclaredMethods();
            for (Method method : methods) {
                //3. 判断每一个方法是否有权限注解
                RequiredPermission anno = method.getAnnotation(RequiredPermission.class);
                if (anno != null) {
                    //拿到方法的权限表达式
                    String exp = PermissionUtil.buildExpression(method);
                    if (!exprs.contains(exp)){//不包含该权限才保存
                        //4. 如果有注释把该方法做成一个权限对象
                        Permission permission = new Permission();
                        permission.setName(anno.value());
                        permission.setExpression(exp);
                        //5. 保存到数据库
                        permissionMapper.insert(permission);
                    }
                }
            }
        }

    }

RoleMapper

    <resultMap id="baseMap" type="Role">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sn" column="sn"/>

        <!--查询关系的多方对象-->
        <collection property="permissions" column="id"
                    select="cn.dusk.rbac.mapper.PermissionMapper.selectPermissionsByRoleId"/>
    </resultMap>

PermissionMapper

    <!--用于关联查询-->
    <select id="selectPermissionsByRoleId" resultType="Permission">
        select
          p.id,p.name
        from permission p join role_permission rp
        on p.id = rp.permission_id
        where rp.role_id = #{roleId}
    </select>

IRoleService

public interface IRoleService {
    void saveOrUpdate(Role entity, Long[] permissionIds);

    void delete(Long id);

    Role get(Long id);

    List<Role> list();

    ResultPage query(QueryObject qo);
}

RoleServiceImpl

@Service
public class RoleServiceImpl implements IRoleService{
    @Autowired
    private RoleMapper roleMapper;

    public void saveOrUpdate(Role entity, Long[] permissionIds) {
        if (entity.getId() == null) {
            roleMapper.insert(entity);
        } else {
            //删除旧的关系
            roleMapper.deleteRelation(entity.getId());
            roleMapper.updateByPrimaryKey(entity);
        }
        //保存角色和权限的关系
        if (permissionIds != null) {
            for (Long pId : permissionIds) {
                roleMapper.insertRelation(entity.getId(),pId);
            }
        }
    }

    public void save(Role role) {
        roleMapper.insert(role);
    }

    public void delete(Long id) {
        //先删除关系
        roleMapper.deleteRelation(id);
        roleMapper.deleteByPrimaryKey(id);
    }

    public Role get(Long id) {
        Role role = roleMapper.selectByPrimaryKey(id);
        return role;
    }

    public List<Role> list() {
        List<Role> list = roleMapper.selectAll();
        return list;
    }

    public ResultPage query(QueryObject qo) {
        int rows = roleMapper.queryForCount(qo);
        List<?> data = roleMapper.queryForList(qo);
        return new ResultPage(qo.getCurrentPage(), qo.getPageSize(), rows, data);
    }

}

三.登录和拦截

登录Controller

LoginController

@Controller
public class LoginController {
    @Autowired
    private IEmployeeService employeeService;
    @RequestMapping("login")
    public String login(String username, String password, Model model){
        try {
            employeeService.login(username, password);
        } catch (Exception e) {
            e.printStackTrace();
            model.addAttribute("msg",e.getMessage());
            return "forward:/login.jsp";
        }
        return "redirect:/main.do";
    }

    @RequestMapping("main")
    public String main(){
        return "main";
    }
}

EmployeeServiceImple

    public void login(String name,String password){
        Employee employee = employeeMapper.selectEmployeeByInfo(name, password);
        if (employee == null) {
            throw new RuntimeException("账号密码不匹配");
        }

        HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest().getSession();
        //把当前登录成功的用户存入session
        session.setAttribute("EMP_IN_SESSION",employee);
        //把当前用户的拥有权限表达式查询出来存入session,目的用于权限检验
        List<String> exps = permissionMapper.selectExpressionsByEmployeeId(employee.getId());
        session.setAttribute("EXPS_IN_SESSION",exps);
    }
}

拦截器

CheckLoginInterceptor

//检查登录拦截器
public class CheckLoginInterceptor extends HandlerInterceptorAdapter {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //从session中取出当前登录的用户
        Object emp = request.getSession().getAttribute("EMP_IN_SESSION");
        if (emp == null) {//没有登录
            response.sendRedirect("/login.jsp");
            return false;//不放行
        }
        return true;//放行
    }
}

mvc.xml

 <!--配置拦截器-->
    <mvc:interceptors>
        <!--登录拦截-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/login.do"/>
            <bean class="cn.dusk.rbac.interceptor.CheckLoginInterceptor"/>
        </mvc:interceptor>
        <!--权限检查拦截器-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/login.do"/>
            <bean class="cn.dusk.rbac.interceptor.SecurityInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

四.安全控制拦截

安全控制拦截

SecurityInterceptor

public class SecurityInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        //获取当前登录的用户
        Employee employee = (Employee)session.getAttribute("EMP_IN_SESSION");
        System.out.println("拦截器: --->" +employee);
        //判断如果是超级管理员
        if (employee.isAdmin()){
            System.out.println("超级管理员");
            return true;
        }
        //拿到当前访问的方法对象
        HandlerMethod hd = (HandlerMethod) handler;
        Method method = hd.getMethod();
        //判断当前方法是否需要权限
        if (!method.isAnnotationPresent(RequiredPermission.class)){
            System.out.println("不需要权限");
            return true;//该方法不需要权限,放行
        }
        //判断当前用户是否拥有执行的权限
        String exp = PermissionUtil.buildExpression(method);
        List<String> exps = (List<String>)session.getAttribute("EXPS_IN_SESSION");
        if(exps.contains(exp)){
            System.out.println("拥有执行权限");
            return true;//当前用户有权限放行
        }
        //没有权限跳转的页面
        System.out.println("没有权限");
        request.getRequestDispatcher("/WEB-INF/views/common/nopermission.jsp").forward(request,response);
        return false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值