shiro--自定义Realm接口

Realm接口

H`7Y%($UHQWCFGSCC33MS7F

在实际项目中,我们不会直接实现Realm接口,而是直接继承AuthorizingRealm,实现认证和授权功能。它需要强制重写两个方法(doGetAuthorizationInfo和doGetAuthenticationInfo)。

自定义realm,从数据库获取密码

shiro.ini

#声明自定义的realm,且为安全管理器指定realm
[main]
definitionRealm=demo.realm.DefinitionRealm
securityManager.realms=$definitionRealm

pom.xml

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.3.2</version>
</dependency>
    <!-- 这里有用到日志打印,所以引入 -->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.14.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.14.1</version>
    </dependency>

demo类

package demo;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ShiroDemo {
    public static void main(String[] args) {
        //1.导入权限ini文件,创建SecurityManagerFactory
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //2.获取SecurityManager,绑定到SecurityUtils中
        SecurityManager securityManager =factory.getInstance();
        SecurityUtils.setSecurityManager( securityManager);
        //3.获取一个用户主体
        Subject currentUser = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("guest", "123");
        currentUser.login(token);
        System.out.println("是否登录成功:"+currentUser.isAuthenticated());
    }
}

自定义realm类

package demo.realm;

import demo.service.SecurityService;
import demo.service.impl.SecurityServiceImpl;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class DefinitionRealm extends AuthorizingRealm {

    /***
     *  鉴权方法
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    /***
     *  认证方法
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取登录名
        String username = (String) authenticationToken.getPrincipal();
        SecurityService service = new SecurityServiceImpl();
        String password = service.findPasswordByUsername(username);
        if("".equals(password)){
            throw new UnknownAccountException("密码不存在!");
        }
        return new SimpleAuthenticationInfo(username, password, getName());
    }
}

编码解码工具类

package tools;

import org.apache.shiro.codec.Base64;
import org.apache.shiro.codec.Hex;

// 编码工具类
public class EncodesUtil {

    /***
     *  Hex   数组转String
     * @param input
     * @return
     */
    public static String encodeHex(byte[] input) {
        return Hex.encodeToString(input);
    }

    /***
     *  Hex    string 转数组
     * @param input
     * @return
     */
    public static byte[] decodeHex(String input) {
        return Hex.decode(input);
    }

    /**
     *  base64 数组转字符串
     * @param input
     * @return
     */
    public static String encodeBase64(byte[] input) {
        return Base64.encodeToString(input);
    }

    /***
     *  base64 字符串转数组
     * @param input
     * @return
     */
    public static byte[] decodeBase64(String input) {
        return Base64.decode(input);
    }
}

生成摘要工具类

package tools;

import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;

import java.util.HashMap;
import java.util.Map;

// 生成摘要
public class DigestsUtil {

    private static final String SHA1 = "SHA-1";
    private static final Integer ITERATIONS = 512;

    /***
     *  SHA1摘要算法
     * @param input  明文字符串
     * @param salt 干扰数据
     * @return
     */
    public static String sha1(String input, String salt) {
        return new SimpleHash(SHA1,input,salt,ITERATIONS).toString();
    }

    /**
     *  随机生成salt
     * @return
     */
    public static String generateSalt() {
        SecureRandomNumberGenerator secureRandomNumberGenerator = new SecureRandomNumberGenerator();
        return secureRandomNumberGenerator.nextBytes().toHex();
    }

    /**
     *  生成密码和salt的密文
     * @param passwordPlan
     * @return
     */
    public static Map<String,String> entryptPassword(String passwordPlan){
        Map<String,String> map = new HashMap<>();
        String salt = generateSalt();
        String password = sha1(passwordPlan,salt);
        map.put("password",password);
        map.put("salt",salt);
        return map;
    }
}

自定义Realm类2

package realm;

import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import service.SecurityService;
import service.impl.SecurityServiceImpl;
import tools.DigestsUtil;

import java.util.Map;

public class DefinitionRealm extends AuthorizingRealm {

    // 在构造函数中修改密码比较器
    public DefinitionRealm(){
        // 指定密码匹配方式sha1
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);
        // 指定密码迭代次数
        matcher.setHashIterations(DigestsUtil.ITERATIONS);
        // 使用父层方法是匹配方式生效
        setCredentialsMatcher(matcher);
    }

    /***
     *  鉴权方法
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    /***
     *  认证方法
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取登录名
        String username = (String) authenticationToken.getPrincipal();
        SecurityService service = new SecurityServiceImpl();
        // 获取数据库密码和salt
        Map<String,String> map = service.findPasswordByUsername(username);
        if(map.isEmpty()){
            throw new UnknownAccountException("账号不存在!");
        }
        String password = map.get("password");
        String salt = map.get("salt");
        return new SimpleAuthenticationInfo(username, password, ByteSource.Util.bytes(salt), getName());
    }
}

SecurityService和SecurityServiceImpl

package service;

import java.util.Map;

// 模拟数据库操作
public interface SecurityService {
    Map<String,String> findPasswordByUsername(String username);
}
package service.impl;

import service.SecurityService;
import tools.DigestsUtil;

import java.util.Map;

public class SecurityServiceImpl implements SecurityService {
    @Override
    public Map<String,String> findPasswordByUsername(String username) {
        return DigestsUtil.entryptPassword("123");
    }
}
posted @ 2026-01-07 21:10  NE_STOP  阅读(6)  评论(0)    收藏  举报