Shiro - 基础篇(下)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: Shiro - 基础篇(下)

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的方式访问数据库,通过与数据库的连接,验证相应的登录用户与授权。    


jdbcRealm新建其实例,并初始化。

Maven中引入mysql的驱动以及相应数据源的类。

新建数据源作为成员变量,并且在静态快中初始化url、username、password等。

将数据源设置到到jdbcrealm中,并且将此realm设置到权限管理中。

之后进行登录等验证,jdbcrealm会在源码的地方写入了默认的进行认证与授权的sql语句,以及表名什么的都规定好了。如果想更改,则写入新的sql语句,并且调用jdbcrealm中的设置认证Query、设置权限Query、设置角色查询的方法,进行修改。

当查询权限的时候,会报错,即便库汇总有次权限,仍旧会报错,因为你需要在jdbcrealm中开启persimisson的为true即可:setPermissionsLookupEnabled(true)。(默认为false)

其他的与之前的认证与授权的步骤一致。


image.pngimage.png

image.png


JdbcRealm 有默认的查询语句图

pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>shiro-learn</artifactId>
        <groupId>com.cheng</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>shiro-test</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

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 + 安全加密


image.png


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<String, String> userMap = new HashMap<>(16);
    {
        userMap.put("cheng", "66f469382db2328c876b700deb336220");
        super.setName("customRealm");
    }
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        Set<String> roles = getRolesByUserName(username);
        Set<String> 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<String> getRolesByUserName(String username) {
        Set<String> set = new HashSet<>();
        // 从数据库或者缓存中获取角色数据
        set.add("admin");
        set.add("user");
        return set;
    }
    private Set<String> getPermissionsByUsername(String username) {
        Set<String> 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");
    }
}

下载地址:shiro-master-Java代码类资源-CSDN下载

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

目录
相关文章
|
9月前
|
存储 缓存 安全
02 Shiro的架构
02 Shiro的架构
32 0
|
12月前
|
存储 算法 数据安全/隐私保护
【Shiro】第三章 Shiro入门(三)
【Shiro】第三章 Shiro入门(三)
65 1
|
12月前
|
安全 数据安全/隐私保护
【Shiro】第三章 Shiro入门(一)
【Shiro】第三章 Shiro入门
59 1
|
12月前
|
缓存 数据库 数据安全/隐私保护
【Shiro】第三章 Shiro入门(四)
【Shiro】第三章 Shiro入门(四)
59 0
|
12月前
|
存储 缓存 安全
Shiro学习之Shiro简介
Shiro学习之Shiro简介
81 0
|
存储 数据采集 缓存
Shiro简介
.什么是Shiro - .ApacheShiro 是一个Java的安全(权限)框架。 - .Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。 - .Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等。
Shiro简介
|
存储 缓存 安全
Shiro框架01之什么是shiro+shiro的架构+权限认证
Shiro框架01之什么是shiro+shiro的架构+权限认证
Shiro框架01之什么是shiro+shiro的架构+权限认证
|
缓存 Java 数据库
Shiro - 基础篇(上)
Shiro - 基础篇(上)
129 0
Shiro - 基础篇(上)
|
缓存 安全 Java
Shiro(一):shiro简介
Shiro(一):shiro简介
185 0
Shiro(一):shiro简介
|
存储 安全 Java
shiro简介
shiro是apache提供的强大而灵活的开源安全框架,它主要用来处理身份认证,授权,企业会话管理和加密。 通俗的讲,shiro的身份认证和授权就是拦截用户未登陆或者没有相应权限的越权访问。 Shiro的企业会话管理实际就是session管理,shiro的session管理可以自定义Session存储的方式,保存到内存、文件、数据库都可以,与传统tomcat等容器无关。