首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot shiro实现权限管理

springboot shiro实现权限管理

作者头像
sucl
发布2019-08-07 14:53:17
1.4K0
发布2019-08-07 14:53:17
举报
文章被收录于专栏:企业平台构建企业平台构建

记得第一次使用shiro是在才入行遇到公司的第一个框架,当时并不知道这是什么,或者说根本就没有安全框架的概念,在慢慢实践中,也对这个有了一定的了解,于是在网上找各种资料学习,了解。记得那时候比较有没的相关博客就是这个了,相信学习shiro的人很多都度过他的博客,内容也比较详细,示例也非常丰富。

开始使用shiro时,是与spring进行整合,可以看这里,当时没有实现太多功能,但是把一些外围的模块都已经实现,而且能够进行多realm匹配。在写这次博客前,也看了下renren-security,同样有很多可以借鉴的地方,所有既然看了这么多,那么自然要把功能做的完善一些了。

当然,此次的系统基础还是上次的springboot jpa搭建开发环境,我会在此基础上进行更新与扩展。

首先还是对shiro有一个初步的认识,当然这些认识都是收集与网络。

首先在学习这个框架时,都基本都会看到的图,那么我们需要了解的无非围绕着shiro里面这些核心的模块,具体是干什么,在什么时候,怎么去用,了解到这些之后,我们就可以按照自己的想法与设计,在适当的场合与环境下正确的使用该框架为我们提供的功能。

Authentication:身份认证/登录,验证用户是不是拥有相应的身份,该对象时对用户身份进行认证时,将相关信息存储的一个媒介,也是由开发者控制炎症逻辑的一个地方;

Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限,与上一个对象一起,都属于自定义Realm时需要由我们自己构建的;

Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的,在shiro是存在三种会话管理的工具,DefaultSessionManager,se环境会还管理;ServletContainerSessionManager,web环境,由web容器管理;DefaultWebSessionManager,支持以上两种,支持自定义会话管理。

Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储,在jar包中包含了大量操作密码的工具类;

Web Support:Web支持,可以非常容易的集成到Web环境,shiro本身不依赖于web环境;

Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;

Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;

Testing:提供测试支持;

Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;

Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

更详细的信息可参考这个博客

在进行编码工作前,还是需要了解一些其他比较重要的 概念,我们知道,shiro的核心就是认证和鉴权,那么实现原理无非是通过servlet的Filter来完成的。其实过滤器是分为两类,一类是完成用户的身份与凭证验证,也就是用户名密码验证,保证能够登录系统,另一类则是权限验证的过滤器,主要是对接口、数据的权限校验。

其内置过滤器有如下这些:

anon:例子/admins/**=anon 没有参数,表示可以匿名使用。

authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数

roles(角色):例子/admins/user/**=rolesadmin,参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles"admin,guest",每个参数通过才算通过,相当于hasAllRoles()方法。

perms(权限):例子/admins/user/**=permsuser:add:*,参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms"user:add:*,user:modify:*",当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。

rest:例子/admins/user/**=restuser,根据请求的方法,相当于/admins/user/**=permsuser:method ,其中method为post,get,delete等。

port:例子/admins/user/**=port8081,当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString

是你访问的url里的?后面的参数。

authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证

ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https

user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查

当然我们还可以自定义一些。具体的说明可以参考这里

那么整合一个shiro框架我们具体需要添加哪些配置呢?如果和springmvc整合过的应该会比较清楚。当然,在shiro-spring这个包中,ShiroWebConfiguration、ShiroWebFilterConfiguration、ShiroAnnotationProcessorConfiguration已经有所有的内容,当然有一些是需要我们根据需要去修改的,毕竟默认的不一定能够满足我们的需要。

shiro基本可以当个黑盒使用,因为如何进行认证,如何进行全校校验已经由框架完成,留给开发者做的就是构建认证与鉴权需要的对象,而这些对象都是以realm的形式存在,我们只需要注入自定义的realm即可,简单的只用继承AuthorizingRealm这个类,实现抽象方法,doGetAuthenticationInfo为认证用的,我们需要构建认证对象,具体的逻辑由我们实现,doGetAuthorizationInfo为鉴权方法,当然是组织鉴权对象的方法。关于shiro,网上有太多太多的文章可以去参考,当然核心内容其实都是一样的。

说了这么多,是时候实际操作了,继续以之前的项目为基础,添加了一个security模块,同时将登入与主页路径进行了修改,因为是直接访问html,所以为了减去views这个路径,同时js也做了少量的修改:

核心其实都在security这包里,可以看到,内容其实不多,因为目前只是完成了认证,即用户登录的校验:

关于登录,有两种方式取实现:

1、自定义一个登录请求,自己完成token的定义与组织,同时完成login操作。这个时候我们会将/login.html过滤指向anon,同时登录行为请求也要设置成anon,本次就是通过这种方式实现:

@PostMapping("/dologin")
public Message login(HttpServletRequest request){
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    String rememberMe = request.getParameter("rememberMe");
    Subject subject = SecurityUtils.getSubject();
    AuthenticationToken toker = new UsernamePasswordToken(username,password,rememberMe);
    Message message = new Message(Message.SUCCESS_CODE,username);
    try {
        boolean reLogin = true;//重新登录
        if(subject.isAuthenticated()){//已经登录如果再次登录
            if(reLogin){
                subject.logout();
            }else{
                return message;
            }
        }
        subject.login(toker);
    } catch (AuthenticationException e) {
        e.printStackTrace();
        message.setCode(Message.FAILURE_CODE);
        message.setInfo(loginFailure(e));
    }
    return message;
}

2、将登录页/login.html过滤器设置为authc(FormAuthenticationFilter),其实就是shiro专门为form表单提交的验证,这样需要我们在一定程度读上进行扩展,比如ajax提交时登录成功或失败的逻辑。但是要注意的是,提交的请求必须与登录页面地址一致,同时为POST类型。这个下次会用到,到时候可以看到具体实现。

然后看看realm:

public class GenericRealm extends AuthorizingRealm {
    @Autowired(required = false)
    private PrincipalService principalService;

    /**
     * 认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        Object principal = token.getPrincipal();
        if(principalService!=null){
            IUser user = principalService.getUser(principal.toString());
            if(user!=null){
                AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),"");
                return authenticationInfo;
            }
        }
        return null;
    }

    /**
     * 鉴权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
}

其实很简单,毕竟是构建对象的过程,所以没有太多的东西,所以关于与shiro的整合目前完成认证就这些东西,但是为了实现一个比较完整的认证授权功能,还有很多需要我们去了解与修改的,将会在下次进行完善。

在此次整合的过程中,也发现一个问题 ,以前和spring整合时,自定义的shiro filter是交由spring管理的,但是和springboot整合时,如果将filter交由spring管理则会出现异常,主要是由于在进行普通请求时也会进入该filter,但是我们要知道,shiro的核心是securityManager,很可能在一般的请求中还没有这个对象,自然就会出现问题,所以在个shiiro配置自定义过滤器时,直接通过new的方式添加即可。

同样,本次的代码在这里

本次项目花费的时间比较长,当然也不可能完成一个成形的项目,问题自然也就存在,但是毕竟是学习,存在一些遗留问题是必要的。目前该项目主要完成了简单的管理功能,如需要添加其他模块也有了一定的参考。由于后期有一些修改,所以之前页面有些写法可能还没来的及更新。

目前学习注重的是广度,因此基本每次进行了交叉方式来构建项目,比如这次用了springboot+jpa+shiro+layui,但是下次可能就不会用 相同的技术了,这样也是为了能快速对各种技术做个了解,并且能够快速上手。

下次将会通过springboot+springsecurity+mybatisplus+vue来搭建项目。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档