shiro的简单介绍

Posted scanner小霸王

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shiro的简单介绍相关的知识,希望对你有一定的参考价值。

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.三种权限认证的方式

以上是关于shiro的简单介绍的主要内容,如果未能解决你的问题,请参考以下文章

shiro的简单介绍

权限控制框架Shiro简单介绍及配置实例

Shiro学习总体介绍

Apache shiro的简单介绍与使用(与spring整合使用)

Shiro Review——Shiro介绍

shiro介绍