shiro的简单介绍

1 篇文章 0 订阅

1.Shiro的简单配置

1) 获取ShiroFilterFactoryBean,作用是在执行相关操作前,先进行功能过滤,拦截所有请求,进入到shiro中进行认证与授权
例如:设置一些拦截的请求
// 身份认证失败,则跳转到登录页面的配置
bean.setLoginUrl(“/tologin”);
// 权限认证失败,则跳转到指定页面
bean.setUnauthorizedUrl(“/tologin”);

2) 创建SecurityManager,来管理shiro;Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

3) Realm 充当了 Shiro 与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro 会从应用配置的 Realm 中查找用户及其权限信息,可见Realm的重要。
当配置 Shiro时,你必须至少指定一个 Realm ,用于认证和(或)授权。配置多个 Realm 是可以的,但是至少需要一个。

Shiro默认使用自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm,以userRealm为例子。

shiroConfig配置:

package com.example.demo.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    //ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);

       /* // 身份认证失败,则跳转到登录页面的配置
        bean.setLoginUrl("/tologin");
        // 权限认证失败,则跳转到指定页面
        bean.setUnauthorizedUrl("/tologin");*/

        //添加shiro的内置过滤器

        /**
         * anno 无需认证就可以访问必须认证了才能访问
         *authc
         * user:必须拥有记住我功能才适用
         * perms :拥有对某个资源的权限才能访问
         * role:拥有某个角色的权限
         */

        //拦截请求
//        Map<String,String> filterChainDefinitionMap =new LinkedHashMap<>();

//        filterChainDefinitionMap.put("/tologin","authc");//免登录验证

//        filterChainDefinitionMap.put("/user/update","anon");//免登录验证
//        filterChainDefinitionMap.put("/user/**","authc");//支持通配符操作  authc
//        filterChainDefinitionMap.put("/user/add","authc");//身份验证

        //方式一:anon,authc
        Map<String,String> filterChainDefinitionMap =new LinkedHashMap<>();

        filterChainDefinitionMap.put("/user/add","anon");
        filterChainDefinitionMap.put("/user/update","authc");
//        filterChainDefinitionMap.put("/**","authc");//支持通配符操作  authc
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);


       /*
       //方式二:perms
       Map<String,String> filterMap =new LinkedHashMap<>();

        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/update","perms[user:update]");
        bean.setFilterChainDefinitionMap(filterMap);*/


       //方式三:roles  加上roleFilter 类,并在UserRealm增加info.addRole("user");
       /*Map<String,String> filterMap =new LinkedHashMap<>();

        filterMap.put("/user/add","roles[user]");
        filterMap.put("/user/update","roles[leader]");
        bean.setFilterChainDefinitionMap(filterMap);*/



        bean.setLoginUrl("/tologin");
        //设置未授权的请求
        bean.setUnauthorizedUrl("/noauth");

        return bean;
    }

    //方式二:user

    /*
    登录接口加上  token.setRememberMe(true);

    <shiro:user>
       当有记住我信息,或已登录,则显示标签体内容
    </shiro:user>

     */

    //DefaultWebSecurityManager2
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager =new DefaultWebSecurityManager();
        //关联userRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //创建realm对象,需要自定义类1
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    //整合shiroDialect:用来整合shiro thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}

userRealm配置

package com.example.demo.config;


import com.example.demo.pojo.User;
import com.example.demo.service.imp.UserServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    UserServiceImpl userService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了=>授权");
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();

//        info.addRole("user");

        info.addStringPermission("user:update");
        info.addStringPermission("user:add");


        //拿到当前用户登陆对象
        Subject subject= SecurityUtils.getSubject();
        User currentUser= (User) subject.getPrincipal();//拿到User对象
//        info.addStringPermission(currentUser.getPerms());//设置当前用户对象

        return info;
    }

    //认证(用户的权限)
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了=>认证");


//        String name="陈汝旭";
//        String password="123456";

        //连接真实数据库
        UsernamePasswordToken userToken =(UsernamePasswordToken) authenticationToken;
//        if (!userToken.getUsername().equals(name)){
//            return null; //抛出异常 unkonwAccountexception登录失败
//        }
//        //密码认证
//        return new SimpleAuthenticationInfo("",password,"");

        User user=userService.queryUserByName(userToken.getUsername());//获取用户名

        String name=user.getName();
        String password=user.getPwd();
        if(user==null){//说明查无此人
            return null;
        }
        return new SimpleAuthenticationInfo(user,password,name);
    }


}


问题:“当对用户执行认证(登录)和授权(访问控制)验证时,Shiro 会从应用配置的 Realm 中查找用户及其权限信息。”,怎么实现?

2.认证的代码流程

1)执行登录的方法
subject.login(token);//执行登陆的方法
2)研究一下login()的方法,进入源码
在这里插入图片描述

3)再进入实现类
(这个login方法大多都是赋值的操作,我们可以只抓住主要的语句分析)
在这里插入图片描述
4)进入这个方法Subject subject = this.securityManager.login(this, token);的实现类
在这里插入图片描述
5)
在这里插入图片描述
6)都是一些异常处理信息,主要研究info = this.doAuthenticate(token);
在这里插入图片描述
7)这里以单realm来研究 doSingleRealmAuthentication
()

在这里插入图片描述
8)再继续下钻到了这里,主要研究 realm.getAuthenticationInfo(token);可以发现getAuthenticationInfo原来是抽象接口Realm的其中一个方法
在这里插入图片描述
9)紧接着进入realm的其中一个实现类AuthenticatingRealm
(个人觉得研究源码可以不全看懂,尽量抓住主要的语句即可,因为获取缓存中的信息无法帮助我们研究流程,可以先不理会)

在这里插入图片描述

10)doGetAuthenticationInfo一直下钻进来,可以看到我们继承的子类的方法AuthenticationInfo,然后在自定义的AuthenticationInfo进行用户认证的操作。
在这里插入图片描述
在这里插入图片描述

3.授权的代码流程

shiro判断权限的方法有subject.isPermitted(“user”),subject.hasRole(“user”);等
以subject.isPermitted(“user”)作为研究

1)点进去它的实现类DelegatingSubject,先判断身份this.hasPrincipals(),在判断授权,所以主要研究isPermitted()
在这里插入图片描述
2)再继续点进去实现类AuthorizingRealm

在这里插入图片描述
3)主要研究getAuthorizationInfo()这个方法

在这里插入图片描述
4)根据上面说的经验,缓存的方法可以先不理会,这里大多也是一些异常处理信息,所以主要研究 info = this.doGetAuthorizationInfo(principals);

在这里插入图片描述
5)再点击进去,又到了我们的老朋友userRealm的doGetAuthorizationInfo
在这里插入图片描述

正常情况这里将从数据库中获取到相对应的权限信息
(为了偷懒,这里就采用写死的方式获取权限)

在这里插入图片描述

4.三种权限认证的方式

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值