志宇-Shiro-Spring

Shiro有什么用

用于用户登录,权限拦截的使用

Shiro架构

在这里插入图片描述

什么是身份认证

Authentication,校验用户名和密码是否可以登录成功,可以登录则创建一个jsessionid给客户端

什么是授权

Authorization,将用户所有的访问权限查询出来,存到内存或库中

什么是会话管理

Session Management, 用户的会话管理,多数情况下是web session,jsessionid不要存储密码,权限等信息

什么是加密

数据加解密,比如密码加解密等,盐值加密等 (Cryptography)

Shiro认证流程

在这里插入图片描述

Subject

我们把用户或者程序称为主体(如用户,第三方服务,cron作业,爬虫),
主体去访问系统或者资源

SecurityManager

安全管理器,Subject的认证和授权都要在安全管理器下进行

Authenticator

认证器,主要负责Subject的认证

Realm

数据域,Shiro和安全数据的连接器,好比jdbc连接数据库; 通过realm获取认证授权相关信息

Authorizer

授权器,主要负责Subject的授权, 控制subject拥有的角色或者权限

Cryptography

加解密,Shiro的包含易于使用和理解的数据加解密方法,简化了很多复杂的api

Cache Manager

缓存管理器,比如认证或授权信息,通过缓存进行管理,提高性能

Shiro的使用

第一步:创建Relam实现类

创建一个或多个Relam类型的类(Relam接口有两个方法要实现)
Relam接口的实现类有两大作用(认证、授权)
1.它用于校验登录,校验是否可以登录,登录成功则返回一个授权对象 (认证)
2.它用于检查该用户是否有指定角色或权限 (授权)
Relam详情
shiro 自己定义了几个Relam,我们可以将用户、角色、权限等信息配置在文件中即可实现认证和授权,然而我们的权限信息要配置到库中,所以要自己定义一个或者多个Relam实现类,来实现认证和授权。

认证

认证会调用如下方法
认证会调用Relam接口实现类的 如下方法

//传入的token中存有 用户登录输入的用户名和密码
//根据传入的token中的用户名(唯一值)获得真正的密码
//根据用户名和真正的密码创建一个AuthenticationInfo对象返回
//返回后shiro会将 token中的信息和AuthenticationInfo对象中的信息进行比对,不同直接报错
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) 

认证流程
在这里插入图片描述

授权

授权会调用如下方法
授权会调用Relam接口实现类的 如下方法

//传入的PrincipalCollection 中存有用户名(唯一值)
//根据用户名从库中查找此用户的角色和权限,将角色和权限 放入到AuthorizationInfo 对象中
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)

授权流程
在这里插入图片描述

第二步:创建SecurityManager实现类

SecurityManager实现类有什么用
SecurityManager用于用户的注销和登录
登录会返回一个Subject,Subject的一个成员变量是 SecurityManager

第三步:将SecurityManager和Relam进行绑定,同时通过SecurityManager获得对应的Subject

     //自己定义的realm
     CustomRealm customRealm = new CustomRealm();
     //Shiro校验的核心对象
     DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
     //将Relam 和 defaultSecurityManager 进行绑定
     defaultSecurityManager.setRealm(customRealm);
     SecurityUtils.setSecurityManager(defaultSecurityManager);
     //获取当前操作的主体
     Subject subject = SecurityUtils.getSubject();
     

第四部:调用认证

     //用户输入的账号密码
     UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("jack", "123");
     //进行认证
     subject.login(usernamePasswordToken);
     System.out.println(" 认证结果:"+subject.isAuthenticated());
     //拿到用户名
     System.out.println(" getPrincipal=" + subject.getPrincipal());

第五步:进行授权

        //进行授权
        subject.checkRole("role1");
        System.out.println("是否有对应的角色:"+subject.hasRole("role1"));
        System.out.println("是否有对应的权限:"+subject.isPermitted("video:add"));

代码

依赖

<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-spring</artifactId>
	<version>1.4.0</version>
</dependency>

java

Relam对象

package com.atguigu.shiro.test;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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 java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 自定义realm
 */
public class CustomRealm extends AuthorizingRealm {
    
    

    private final Map<String,String> userInfoMap = new HashMap<>();
    {
    
    
        userInfoMap.put("jack","123");
        userInfoMap.put("xdclass","456");
    }
    //role -> permission
    private final Map<String,Set<String>> permissionMap = new HashMap<>();
    {
    
    

        Set<String> set1 = new HashSet<>();
        Set<String> set2 = new HashSet<>();

        set1.add("video:find");
        set1.add("video:buy");
        
        set2.add("video:add");
        set2.add("video:delete");

        permissionMap.put("jack",set1);
        permissionMap.put("xdclass",set2);

    }
    //user -> role
    private final Map<String,Set<String>> roleMap = new HashMap<>();
    {
    
    
        Set<String> set1 = new HashSet<>();
        Set<String> set2 = new HashSet<>();
        set1.add("role1");
        set1.add("role2");
        set2.add("root");
        roleMap.put("jack",set1);
        roleMap.put("xdclass",set2);

    }
    //进行权限校验的时候会调用
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    
    
        System.out.println("权限 doGetAuthorizationInfo");

        String name = (String)principals.getPrimaryPrincipal();

        Set<String> permissions = getPermissionsByNameFromDB(name);

        Set<String> roles = getRolesByNameFromDB(name);

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);

        return simpleAuthorizationInfo;
    }





    //当用户登陆的时候会调用
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    
    

        System.out.println("认证 doGetAuthenticationInfo");

        //从token获取身份信息,token代表用户输入的信息
        String name = (String)token.getPrincipal();

        //模拟从数据库中取密码
        String pwd = getPwdByUserNameFromDB(name);

        if( pwd == null || "".equals(pwd)){
    
    
            return null;
        }

        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, pwd, this.getName());

        return simpleAuthenticationInfo;
    }


    /**
     * 模拟从数据库获取用户角色集合
     * @param name
     * @return
     */
    private Set<String> getRolesByNameFromDB(String name) {
    
    
        return roleMap.get(name);

    }

    /**
     *  模拟从数据库获取权限集合
     * @param name
     * @return
     */
    private Set<String> getPermissionsByNameFromDB(String name) {
    
    
        return permissionMap.get(name);
    }


    private String getPwdByUserNameFromDB(String name) {
    
    

        return userInfoMap.get(name);
    }
}

调用类

package com.atguigu.shiro.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;


public class Luck{
    
    


    public void testAuthentication() {
    
    
        //自己定义的realm
        CustomRealm customRealm = new CustomRealm();
        //Shiro校验的核心对象
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //将Relam 和 defaultSecurityManager 进行绑定
        defaultSecurityManager.setRealm(customRealm);
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //获取当前操作的主体
        Subject subject = SecurityUtils.getSubject();

        //用户输入的账号密码
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("jack", "123");

        subject.login(usernamePasswordToken);


        //登录
        System.out.println(" 认证结果:"+subject.isAuthenticated());

        //拿到主体标示属性
        System.out.println(" getPrincipal=" + subject.getPrincipal());

        subject.checkRole("role1");

        System.out.println("是否有对应的角色:"+subject.hasRole("role1"));
        System.out.println("是否有对应的权限:"+subject.isPermitted("video:add"));
    }

    public static void main(String[] args) {
    
    
        new Luck().testAuthentication();
    }
}

猜你喜欢

转载自blog.csdn.net/fenkanghong9779/article/details/105756915