初次使用Shiro进行加密密码的算法实例

场景

Apache Shiro 是一个强大易用的 Java 安全框架,用以执行身份验证、授权、密码和会话管理,而且可以方便地被 Spring Boot 所集成。
大部分 Web 应用的用户密码一般通过散列算法 + 盐的形式持久化在数据库中。在使用 Shiro 进行身份验证时,可以在 Shiro 配置类中配置密码散列匹配器,来对数据库中保存的密码进行验证。

实现

1.在接收到密码的地方

String username = request.getUsername();
String password = request.getPassword();
String salt = SequenceUtil.getInst().getRandomCode(6);
String encryptPassword = ShiroHelper.SHA1(password,username+salt);

初次使用SequenceUtil.getInst().getRandomCode(6);生成盐值,存到数据库。

以后登录验证时屏蔽这段代码,使用数据库存的盐值去生成加密的密码。

其中SequenceUtil代码为:

import org.apache.commons.lang3.RandomStringUtils;
public class SequenceUtil {

    private static SequenceUtil instance;

    public synchronized static SequenceUtil getInst() {
        if (instance == null) {
            instance = new SequenceUtil();
        }
        return instance;
    }

  
    public synchronized String getRandomCode(int num){
        String code = null;
        try {
            code = RandomStringUtils.random(num, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
          
        } catch (Exception e) {
          
        }
        return code;
    }
}

通过RandomStringUtils的random方法从第二个参数中随机选取num个。

2.在ShiroHelper中

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;

public class ShiroHelper {

    public  static final String SHIRO_USER = "badao";

    private static final String NAMES_DELIMETER = ",";
    /**
     * 散列算法
     */
    public static final String ALGORITHM_SHA1 = "SHA-1";

    /**
     * 循环次数
     */
    public final static int HASH_ITERATIONS = 10;

    /**
     * shiro密码加密工具类
     *
     * @param credentials 密码
     * @param saltSource  密码盐
     * @return
     */
    public static String SHA1(String credentials, String saltSource) {
        return new SimpleHash(ALGORITHM_SHA1, credentials, saltSource, HASH_ITERATIONS).toHex();
    }

    /**
     * 获取随机盐值
     *
     * @param length 字节长度,一个字节2位16进制数表示
     * @return
     */
    public static String getRandomSalt(int length) {
        return new SecureRandomNumberGenerator().nextBytes(length).toHex();
    }

    /**
     * 获取当前 Subject
     *
     * @return Subject
     */
    public static Subject getSubject() {
        return SecurityUtils.getSubject();
    }

    /**
     * 获取封装的 ShiroUser
     *
     * @return ShiroUser
     */
    public static ShiroDefaultEntity getUser() {
        if (isGuest()) {
            return null;
        } else {
            return (ShiroDefaultEntity) getSubject().getPrincipals().getPrimaryPrincipal();
        }
    }

    /**
     * 从shiro获取session
     */
    public static Session getSession() {
        return getSubject().getSession();
    }

    /**
     * 获取shiro指定的sessionKey
     */
    @SuppressWarnings("unchecked")
    public static <T> T getSessionAttr(String key) {
        Session session = getSession();
        return session != null ? (T) session.getAttribute(key) : null;
    }

    /**
     * 设置shiro指定的sessionKey
     */
    public static void setSessionAttr(String key, Object value) {
        Session session = getSession();
        session.setAttribute(key, value);
    }

    /**
     * 移除shiro指定的sessionKey
     */
    public static void removeSessionAttr(String key) {
        Session session = getSession();
        if (session != null)
            session.removeAttribute(key);
    }

    /**
     * 验证当前用户是否属于该角色?,使用时与lacksRole 搭配使用
     *
     * @param roleName 角色名
     * @return 属于该角色:true,否则false
     */
    public static boolean hasRole(String roleName) {
        return getSubject() != null && roleName != null
                && roleName.length() > 0 && getSubject().hasRole(roleName);
    }

    /**
     * 与hasRole标签逻辑相反,当用户不属于该角色时验证通过。
     *
     * @param roleName 角色名
     * @return 不属于该角色:true,否则false
     */
    public static boolean lacksRole(String roleName) {
        return !hasRole(roleName);
    }

    /**
     * 验证当前用户是否属于以下任意一个角色。
     *
     * @param roleNames 角色列表
     * @return 属于:true,否则false
     */
    public static boolean hasAnyRoles(String roleNames) {
        boolean hasAnyRole = false;
        Subject subject = getSubject();
        if (subject != null && roleNames != null && roleNames.length() > 0) {
            for (String role : roleNames.split(NAMES_DELIMETER)) {
                if (subject.hasRole(role.trim())) {
                    hasAnyRole = true;
                    break;
                }
            }
        }
        return hasAnyRole;
    }

    /**
     * 验证当前用户是否属于以下所有角色。
     *
     * @param roleNames 角色列表
     * @return 属于:true,否则false
     */
    public static boolean hasAllRoles(String roleNames) {
        boolean hasAllRole = true;
        Subject subject = getSubject();
        if (subject != null && roleNames != null && roleNames.length() > 0) {
            for (String role : roleNames.split(NAMES_DELIMETER)) {
                if (!subject.hasRole(role.trim())) {
                    hasAllRole = false;
                    break;
                }
            }
        }
        return hasAllRole;
    }

    /**
     * 验证当前用户是否拥有指定权限,使用时与lacksPermission 搭配使用
     *
     * @param permission 权限名
     * @return 拥有权限:true,否则false
     */
    public static boolean hasPermission(String permission) {
        return getSubject() != null && permission != null
                && permission.length() > 0
                && getSubject().isPermitted(permission);
    }

    /**
     * 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。
     *
     * @param permission 权限名
     * @return 拥有权限:true,否则false
     */
    public static boolean lacksPermission(String permission) {
        return !hasPermission(permission);
    }

    /**
     * 已认证通过的用户,不包含已记住的用户,这是与user标签的区别所在。与notAuthenticated搭配使用
     *
     * @return 通过身份验证:true,否则false
     */
    public static boolean isAuthenticated() {
        return getSubject() != null && getSubject().isAuthenticated();
    }

    /**
     * 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。。
     *
     * @return 没有通过身份验证:true,否则false
     */
    public static boolean notAuthenticated() {
        return !isAuthenticated();
    }

    /**
     * 认证通过或已记住的用户。与guset搭配使用。
     *
     * @return 用户:true,否则 false
     */
    public static boolean isUser() {
        return getSubject() != null && getSubject().getPrincipal() != null;
    }

    /**
     * 验证当前用户是否为“访客”,即未认证(包含未记住)的用户。用user搭配使用
     *
     * @return 访客:true,否则false
     */
    public static boolean isGuest() {
        return !isUser();
    }

    /**
     * 输出当前用户信息,通常为登录帐号信息。
     *
     * @return 当前用户信息
     */
    public static String principal() {
        if (getSubject() != null) {
            Object principal = getSubject().getPrincipal();
            return principal.toString();
        }
        return "";
    }

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霸道流氓气质

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值