Shiro - 基础篇

Shiro - 基础篇_第1张图片

Shiro - 基础篇_第2张图片

由于权限管理模块一般都是在资源一层,如果更深一层的话,则可能会与业务代码进行耦合,故提倡Shiro做权限管理,Spring官网也是用Shiro进行的权限管理。

Shiro - 基础篇_第3张图片

  • SUB 主体
  • Authenticator 认证器(登陆)
  • Authorizer 授权器(访问权限)
  • SessionManager Shiro自己的Session不依赖于Web
  • SessionDAO Session操作增删改查
  • CacheManager 缓存操作(缓存角色和权限)
  • Reaims Shiro和数据库直接的一个桥梁

Shiro - 基础篇_第4张图片

Shiro - 基础篇_第5张图片
 

AuthenticationTest.java

package com.cheng.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;

public class AuthenticationTest {

    SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();

    @Before
    public void addUser() {
        simpleAccountRealm.addAccount("cheng", "123", "admin", "user");
    }

    @Test
    public void testAuthentication() {

        // 1. 构建 SecurityManager 环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(simpleAccountRealm);

        // 2. 主体提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken("cheng", "123");
        subject.login(token);

        System.out.println("isAuthenticated: " + subject.isAuthenticated());

        // 检查用户是否有 admin 角色
        subject.checkRoles("admin", "user");

        // 退出认证
        subject.logout();

        System.out.println("isAuthenticated: " + subject.isAuthenticated());
    }
}

 

IniRealm

Shiro的IniRealm 形式:此形式主要是将数据存放到相应的user.ini即文件系统中,通过给定的格式,从文件中查找相应的数据是否存在。

步骤:

  1. 删除之前SimpleAccountRealm,在实体中创建IniRealm并实例化。在构造方法中传入相应的user.ini地址。此文件地址一般写为:classpath:user.ini的形式。需要在相应的包中建立resource文件夹,并且放入user.ini文件。
  2. user.ini文件的定义格式为:[users] 用户名=密码,角色 [roles] 角色=权限名(例子:amdin=user:delete,user:update)
  3. 与之前认证与授权步骤一样,直接将IniRealm放入到SecurityManager中,进行登录认证,之后进行checkRoles验证与checkPersimmon验证权限等操作即可。
  4. Ps:中括号表示:要同时具备里面的角色才行,是 && 的关系。

user.ini

[users]
cheng = 123,admin
[roles]
admin = user:delete,user:update

IniRealmTest.java

package com.cheng.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

public class IniRealmTest {

    IniRealm iniRealm = new IniRealm("classpath:user.ini");

    @Test
    public void testAuthentication() {

        // 1. 构建 SecurityManager 环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(iniRealm);

        // 2. 主体提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken("cheng", "123");
        subject.login(token);

        System.out.println("isAuthenticated: " + subject.isAuthenticated());

        subject.checkRole("admin");

        subject.checkPermission("user:delete");
        subject.checkPermission("user:update");
    }
}

 

JdbcRealm

JdbcRealm的方式访问数据库,通过与数据库的连接,验证相应的登录用户与授权。

  1. jdbcRealm新建其实例,并初始化。
  2. Maven中引入mysql的驱动以及相应数据源的类。
  3. 新建数据源作为成员变量,并且在静态快中初始化url、username、password等。
  4. 将数据源设置到到jdbcrealm中,并且将此realm设置到权限管理中。
  5. 之后进行登录等验证,jdbcrealm会在源码的地方写入了默认的进行认证与授权的sql语句,以及表名什么的都规定好了。如果想更改,则写入新的sql语句,并且调用jdbcrealm中的设置认证Query、设置权限Query、设置角色查询的方法,进行修改。
  6. 当查询权限的时候,会报错,即便库汇总有次权限,仍旧会报错,因为你需要在jdbcrealm中开启persimisson的为true即可:setPermissionsLookupEnabled(true)。(默认为false)
  7. 其他的与之前的认证与授权的步骤一致。

Shiro - 基础篇_第6张图片

JdbcRealm 有默认的查询语句图

pom.xml



    
        shiro-learn
        com.cheng
        1.0-SNAPSHOT
    
    4.0.0

    shiro-test

    

        
            org.apache.shiro
            shiro-core
            1.4.0
        

        
            mysql
            mysql-connector-java
            5.1.46
        

        
            com.alibaba
            druid
            1.1.6
        

        
            junit
            junit
            4.12
        

    

JdbcRealmTest.java

package com.cheng.test;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

public class JdbcRealmTest {

    DruidDataSource dataSource = new DruidDataSource();

    {
        dataSource.setUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUsername("root");
        dataSource.setPassword("zy159357");
    }

    @Test
    public void testAuthentication() {

        JdbcRealm jdbcRealm = new JdbcRealm();
        jdbcRealm.setDataSource(dataSource);
        // 查询权限数据,默认为 false
        jdbcRealm.setPermissionsLookupEnabled(true);

        String sql = "select password from test_user where user_name = ?";
        jdbcRealm.setAuthenticationQuery(sql);

        String roleSql = "select role_name from test_user_role  where user_name = ?";
        jdbcRealm.setUserRolesQuery(roleSql);

  		String permissionSql = "select permission_name from test_user_permission  where role_name = ?";
        jdbcRealm.setPermissionsQuery(permissionSql);

        // 1. 构建 SecurityManager 环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(jdbcRealm);

        // 2. 主体提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken("cheng", "123");
        subject.login(token);

        System.out.println("isAuthenticated: " + subject.isAuthenticated());

        subject.checkRole("admin");
        subject.checkRoles("admin", "user");

        subject.checkPermission("user:select");
    }
}

 

自定义Realm + 安全加密

Shiro - 基础篇_第7张图片

CustomRealm.java

package com.cheng.shiro.realm;

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.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

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

    Map userMap = new HashMap<>(16);

    {
        userMap.put("cheng", "66f469382db2328c876b700deb336220");

        super.setName("customRealm");
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

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

        Set roles = getRolesByUserName(username);

        Set permissions = getPermissionsByUsername(username);

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);

        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        // 1. 从主体传过来的认证信息中,获得用户名
        String username = (String) authenticationToken.getPrincipal();

        // 2. 通过用户名到数据库中获取凭证
        String password = getPasswordByUsername(username);
        if (password == null) {
            return null;
        }

        SimpleAuthenticationInfo authenticationInfo =
                new SimpleAuthenticationInfo(username, password, "customRealm");

        // 设置加密的 盐
        authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("cheng"));

        return authenticationInfo;
    }

    private Set getRolesByUserName(String username) {
        Set set = new HashSet<>();

        // 从数据库或者缓存中获取角色数据
        set.add("admin");
        set.add("user");
        return set;
    }

    private Set getPermissionsByUsername(String username) {

        Set set = new HashSet<>();

        set.add("user:delete");
        set.add("user:update");
        return set;
    }

    /**
     * 模拟数据库查询凭证
     */
    private String getPasswordByUsername(String username) {
        return userMap.get(username);
    }

    public static void main(String[] args) {
        // 密码 + 盐 加密后的结果
        Md5Hash md5Hash = new Md5Hash("123", "cheng");
        System.out.println(md5Hash.toString());
    }
}

CustomerRealmTest.java

package com.cheng.test;

import com.cheng.shiro.realm.CustomRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

/**
 * 自定义 Realm
 */
public class CustomerRealmTest {
	
    @Test
    public void testAuthentication() {

        CustomRealm customRealm = new CustomRealm();

        // 1. 构建 SecurityManager 环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(customRealm);

        // 加密
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        // 加密算法名称
        matcher.setHashAlgorithmName("md5");
        // 加密次数
        matcher.setHashIterations(1);

        // 自定义 Realm 中设置加密对象
        customRealm.setCredentialsMatcher(matcher);

        // 2. 主体提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken("cheng", "123");
        subject.login(token);

        System.out.println("isAuthenticated: " + subject.isAuthenticated());

        subject.checkRole("admin");

        subject.checkPermission("user:delete");
        subject.checkPermission("user:update");
    }
}

 

下载地址:https://download.csdn.net/download/dream_weave/10892755

更多教程:Shiro - Spring + Jedis(会话、缓存、自动登录)整合篇

你可能感兴趣的:(Shiro,权限,角色,Realm,安全加密,#,Shiro)