SpringBoot集成SpringSecurity(一) 入门

需求

公司打算重构权限系统,主要因为现有的系统存在这些问题:

  1. 查询用户步骤繁琐:选系统(主要是这一点)——用户名——查询按钮;

  2. 简化权限只分配到角色:现在权限全部汇总到一起,不知道权限从何而来;

  3. 角色承担职责过多,杂而乱;

  4. 登录名不唯一,无账号找回功能

总之就是一个很乱的权限系统,考虑到security的强大功能,灵活易拓展(各种自定义),耦合性低,所以打算用security去是实现。

其实,我是不建议大家直接去了解security,大家可以先考虑一下没引入security之前,登录认证授权流程是怎样的,因为毕竟security也是按照这些去封装代码的。

如果直接去了解security的话,多少会有点迷茫和含糊,因为它比较复杂(功能特别强大,拓展性极好),在知道本质之后去了解,一切都会显得很清晰~~~

为了方便入门,下面我主要讲解的是没有被security封装之前的登录授权流程代码~~

如果这些您已了解,那么请直接看下篇的登录流程源码分析。


前提

在了解security之前,我们必须知道这几个东西:

  1. 什么是会话?

  2. 授权的数据模型?

  3. RBAC方式


什么是会话?

用户认证通过后,为了避免用户的每次操作都进行认证可将用户的信息保证在会话中。会话就是系统为了保持当前 用户的登录状态所提供的机制。

常见的方式有两种:

  1. 基于session方式;
  2. 基于token方式;

session方式,我们可能很熟悉了,它的交互流程就是,用户认证成功后,在服务端生成用户相关的数据保存在session(当前会话)中,发给客户端的 sesssion_id 存放到 cookie 中,这样用户客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数 据,以此完成用户的合法校验,当用户退出系统或session过期销毁时,客户端的session_id也就无效了。如图:
在这里插入图片描述
基于token方式如下图:

​ 它的交互流程是,用户认证成功后,服务端生成一个token发给客户端,客户端可以放到 cookie 或 localStorage 等存储中,每次请求时带上 token,服务端收到token通过验证后即可确认用户身份
在这里插入图片描述

基于session的认证方式由Servlet规范定制,服务端要存储session信息需要占用内存资源,客户端需要支持 cookie;基于token的方式则一般不需要服务端存储token,并且不限制客户端的存储方式。如今移动互联网时代 更多类型的客户端需要接入系统,系统多是采用前后端分离的架构进行实现,所以基于token的方式更适合。

授权的数据模型

即表结构的对应关系
在这里插入图片描述

主体(用户id、账号、密码、…)

角色(角色id、角色名称、…)

主体(用户)和角色关系(用户id、角色id、…)

权限(权限id、权限标识、权限名称、资源名称、资源访问地址、…)

角色与权限的关系(角色id,权限id…)

RBAC方式

如何实现授权,可以通过RBAC方式实现授权,RBAC有两种方式:

  1. 基于角色的访问控制(存在硬编码问题)
  2. 基于资源的访问控制(推荐)

具体如下:

基于角色的访问控制

用户必须 具有查询工资权限才可以查询员工工资信息等,访问控制流程如下:

在这里插入图片描述

根据上图中的判断逻辑,授权代码可表示如下:

if(主体.hasRole("总经理角色id")){ 
	查询工资 
}

如果上图中查询工资所需要的角色变化为总经理和部门经理,此时就需要修改判断逻辑为“判断用户的角色是否是 总经理或部门经理”,修改代码如下:

if(主体.hasRole("总经理角色id") ||  主体.hasRole("部门经理角色id")){
	查询工资 
}

由此,我们可以看出,以上存在硬编码问题!

基于资源的访问控制

在这里插入图片描述

根据上图中的判断,授权代码可以表示为:

if(主体.hasPermission("查询工资权限标识")){     
	查询工资 
}

优点:系统设计时定义好查询工资的权限标识,即使查询工资所需要的角色变化为总经理和部门经理也不需要修改 授权代码,系统可扩展性强


入门

在了解security之前,我们先来了解一下没有security的时候,登录流程是怎么走的。

为了防止迷路,我先说一下步骤:

  1. 搭建项目环境(applicationcontext.xml,springmvc.xml,登录页面,初始化spring容器等);

  2. 配置所需要的bean以及业务;

  3. 认证逻辑;

  4. 会话管理

    • 基于session,通过HttpSession操作,主要用到的方法有setAttribute(),getAttribute(),invalidate();
    • 在认证成功的时候调用setAttribute()方法储存,在访问资源的时候调用getAttribute(),在登出的时候调用invalidate();
  5. 授权功能

    其实授权的本质就是一个拦截器,通过页面当前访问的资源与后台查到的用户权限做匹配,如果一致,则放行。

以上部分我们重点讲解3,5其余步骤略。

认证逻辑

认证的流程为:

  1. 首先,当用户请求过来的时候,我们是不是需要判断一下它传过来的值是否为空,即用户名或者密码为空;
  2. 其次我们需要拿着用户名字去我们数据库查询是否有这个用户,没有的话,直接抛异常“没有该用户”;
  3. 如果通过用户名查到用户的话,那我们是不是需要用它来跟用户输入的值去做对比,如果一致则放行,不一致则抛异常(“账号或密码错误”);

以上三点用代码来表示的话,如下:

public User authentication(AuthenticationRequest authenticationRequest){
        if(authenticationRequest == null || StringUtils.isEmpty(authenticationRequest.getUsername()) || StringUtils.isEmpty(authenticationRequest.getPassword())){
            throw new RuntimeException("用户名或密码为空");
        }

        User user = userDao.getUserByUsername(authenticationRequest.getUsername());
        if(Objects.isNull(user)){
            throw new RuntimeException("该用户不存在!");
        }
        if(!authenticationRequest.getPassword().equals(a.getPassword())){
            throw new RuntimeException("用户名或密码错误!");
        }
        return user;
    }

其实这段代码被security封装到了一个叫userDetailService的类中,但是其最本质的功能跟这个是一样的;

授权功能

流程如下:

  1. 为了模仿授权功能的实现,我们增加一个r1的资源(访问此路径的前提是在用户已认证的情况下),想要访问此资源必须要有p1的权限;
  2. 现在一名叫‘王五’的用户想访问它,所以我们就需要判断一下王五是否含有p1权限;
  3. 如果含有p1权限,则放行;

代码如下:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //用户身份信息
        Object object = request.getSession().getAttribute(UserDto.SESSION_USER_KEY);
        if(object == null){
            //没有认证
            writeContent(response,"请登录");
        }
        UserDto userDto = (UserDto) object;
        //请求的url
        String requestURI = request.getRequestURI();
        if( userDto.getAuthorities().contains("p1") && requestURI.contains("/r/r1")){
            return true;
        }
        writeContent(response,"没有权限,拒绝访问");

        return false;
    }

其实这块代码也被security封装到了userDetailService中,但是security可能跟这个有点出入,security它引入了一个AccessDecisionVoter用于投票选举机制,又采用3种模式判定,这个我们在后面详细解释…

总结

至此,我们security种的认证授权最本质的代码就说到这了,当然security的功能要比这强大太多,下一结我们去看看security的底层源码,看看它就是是怎么进行登录授权流程的。

下一篇链接:SpringBoot集成SpringSecurity(二) 登录认证流程解析

参考文献

推荐视频:https://www.bilibili.com/video/av73730658?from=search&seid=10438598876647660573

因为我就是用这个视频去入手的,特别适合入门,讲的很透彻,大家感兴趣的可以看看

另:如有总结不对的地方,麻烦大家指出,希望我们共同给进步_

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值