Hello shiro基础知识整理---shiro基础篇

转载请注明出处:
牵手生活--:笔记是整理思路方式,分享是一个美德,牵手是我的生活方式


shiro概述参见shiro(java安全框架)

shiro(java安全框架)

Hello shiro基础知识整理---shiro基础篇_第1张图片
shiro整体架构

认识shiro需要理解的内容


Hello shiro基础知识整理---shiro基础篇_第2张图片
认识shiro

在idea中创建一个maven javaweb工程HelloShiro

配置pom.xml文件引入shiro核心包和junit

    
        
        
            org.apache.shiro
            shiro-core
            1.4.0
        

        
        
            junit
            junit
            3.8.1
        
        
            junit
            junit
            4.0
        


    

shiro认证

创建一个单元测试类(junit)AuthenticationTest.java,并测试

模拟认证请求的过程


Hello shiro基础知识整理---shiro基础篇_第3张图片
shiro认证过程
Hello shiro基础知识整理---shiro基础篇_第4张图片
shiro认证单元测试结果
package com.younghare.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("Mark","123456");
    }

    @Test
    public void testAuthentication(){
        //构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(simpleAccountRealm);  //设置Realm到环境中

        //设置提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);  //设置环境
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken taken = new UsernamePasswordToken("Mark","123456");

        subject.login(taken);//登录认证数据


        boolean  isAuthenticated = subject.isAuthenticated();
        System.out.println("认证的结果是:"+isAuthenticated);

        //退出登录
        subject.logout();
        System.out.println("logout后认证的结果是:"+subject.isAuthenticated());

    }
    
}

Shiro授权

Hello shiro基础知识整理---shiro基础篇_第5张图片
shiro授权过程

修改单元测试,并查看结果


Hello shiro基础知识整理---shiro基础篇_第6张图片
检查角色结果
public class AuthenticationTest {

    SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();

    @Before //所以测试方法运行前,都会运行
    public void addUser(){
        simpleAccountRealm.addAccount("Mark","123456","admin","user"); //第3个参数开始是角色
    }

    @Test
    public void testAuthentication(){
        //构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(simpleAccountRealm);  //设置Realm到环境中

        //设置提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);  //设置环境
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken taken = new UsernamePasswordToken("Mark","123456");

        subject.login(taken);//登录认证数据


        boolean  isAuthenticated = subject.isAuthenticated();
        System.out.println("认证的结果是:"+isAuthenticated);

        subject.checkRole("admin1");//判断用户是否有admin的角色,可同时检查多个角色

    }  
}

IniRealm讲解

创建IniRealm的配置文件user.ini


Hello shiro基础知识整理---shiro基础篇_第7张图片
user.ini内容
[users]
Mark = 123456,admin
[roles]
admin=user:delete

创建一个单元测试类(junit)IniRealmTest.java,并测试

public class IniRealmTest {
    @Test
    public void testAuthentication(){
        IniRealm iniRealm = new IniRealm("classpath:user.ini");
        //构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(iniRealm);

        //设置提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);  //设置环境
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken taken = new UsernamePasswordToken("Mark","123456");
        subject.login(taken);//登录认证数据

        System.out.println("认证的结果是:"+subject.isAuthenticated());
        subject.checkRole("admin");

        subject.checkPermission("user:update");//是否具备用户删除的权限,配置信息在user.ini文件中
    }

}

Hello shiro基础知识整理---shiro基础篇_第8张图片
目录结构
Hello shiro基础知识整理---shiro基础篇_第9张图片
IniRealm单元测试结果

JdbcRealm讲解

在pom.xml中添加对mysql 和数据源druid的引入
        
        
            mysql
            mysql-connector-java
            6.0.6
        

        
        
            com.alibaba
            druid
            1.1.6
        
在mysql数据库中创建对应的表users,结构如下
Hello shiro基础知识整理---shiro基础篇_第10张图片
auth库的users表结构及数据

其他表的机构可以参考JdbcRealm源码的默认sql语句部分

编辑测试用例IniRealmTest.java 并测试
public class IniRealmTest {
    DruidDataSource dataSource = new DruidDataSource ();
    {
        dataSource.setUrl("jdbc:mysql://47.**.**.27:3306/auth?serverTimezone=UTC");
        //dataSource.setUrl("jdbc:mysql://localhost:3306/auth?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("你的密码");

    }

    
    @Test
    public void testAuthentication(){
        JdbcRealm jdbcRealm = new JdbcRealm();
        /*要首先建一个test的数据库,然后建一个users(username,password)的表,然后插入数据(‘Mark’,'123456)才行*/
        jdbcRealm.setDataSource(dataSource);//设置数据源

        //构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(jdbcRealm);
        jdbcRealm.setPermissionsLookupEnabled(true);//默认jdbcRealm不会去查询权限数据


        //设置提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);  //设置环境
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken taken = new UsernamePasswordToken("Mark","123456");
        subject.login(taken);//登录认证数据

        System.out.println("认证的结果是:"+subject.isAuthenticated());
        //subject.checkRole("admin"); 

    }

}

JdbcRealm源码中默认的sql查询语句

里面有对应默认表
问题
现在的问题是我们并设置查询语句呀,看看JdbcRealm的源码发现里面有默认的查询语句

Hello shiro基础知识整理---shiro基础篇_第11张图片
JdbcRealm源码中默认的sql查询语句

所以我们应该根据默认的语句创建几张对应的表users、user_roles、roles_permissions、user_roles

idea配置database连接mysql

其他配置如:


image.png

创建test_user表,并添加数据


Hello shiro基础知识整理---shiro基础篇_第12张图片
test_user表与数据

创建test_user_role表,并添加数据


Hello shiro基础知识整理---shiro基础篇_第13张图片
test_user_role表结构与数据

IniRealmTest的testAuthentication方法修改如下


Hello shiro基础知识整理---shiro基础篇_第14张图片
测试方法修改
  
    @Test
    public void testAuthentication(){
        JdbcRealm jdbcRealm = new JdbcRealm();
        /*要首先建一个test的数据库,然后建一个users(username,password)的表,然后插入数据(‘Mark’,'123456)才行*/
        jdbcRealm.setDataSource(dataSource);//设置数据源
        //jdbcRealm.setPermissionsLookupEnabled(true);//默认jdbcRealm不会去查询权限数据

        //不采用jdbcRealm默认表的情况,需要设置sql语句
        //SELECT PASSWORD FROM test_user WHERE user_name = "younghare"
        String sql = "SELECT PASSWORD FROM test_user WHERE user_name = ?";
        jdbcRealm.setAuthenticationQuery(sql);
        //sql语句的写法参考JdbcRealm源码
        String sqlRole = "SELECT role_name FROM test_user_role where user_name = ?";
        jdbcRealm.setUserRolesQuery(sqlRole);
        


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

        //设置提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);  //设置环境
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken taken = new UsernamePasswordToken("younghare","741852");
        subject.login(taken);//登录认证数据

        System.out.println("认证的结果是:"+subject.isAuthenticated());
        subject.checkRole("admin");

    }

IntelliJ IDEA中如何显示和关闭----工具栏,目录栏,

自定义Realm(需要继承AuthorizingRealm,实现doGetAuthorizationInfo和doGetAuthenticationInfo接口)

自定义CustomRealm.java
package com.younghare.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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class CustomRealm extends AuthorizingRealm {
    /*模拟用户的数据库信息*/
    Map userMap = new HashMap<>(16);
    {
        userMap.put("younghare","123456");
        userMap.put("xiaoming","654321");
        super.setName("customRealm");//设置自己的realmName

    }

    @Override //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String userName = (String) principalCollection.getPrimaryPrincipal();
        //从数据库或缓冲中获得角色数据
        Set roles = getRolesByUserName(userName);
        //从数据库或缓冲中获得权限数据
        Set permissions = getPermissionsByUserName(userName);

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

        return simpleAuthorizationInfo;
    }

    /**
     * 模拟用户权限数据
     * @param userName
     * @return
     */
    private Set getPermissionsByUserName(String userName) {
        Set sets = new HashSet<>();
        sets.add("user:myAdd");
        sets.add("user:delete");
        sets.add("user:update");
        return sets;

    }

    /**
     * 模拟角色数据
     * @param userName
     * @return
     */
    private Set getRolesByUserName(String userName) {
        Set sets = new HashSet<>();
        sets.add("admin");
        sets.add("user");
        return sets;
    }

    @Override //认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        /*从主体传来的认证信息中,获得用户名*/
        String userName = (String) authenticationToken.getPrincipal();
        /*通过用户名到数据库中获取凭证*/
        String password = getPasswordByUserName(userName);
        if (password == null){
            return null;
        }

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

        return authenticationInfo;
    }

    /**
     * 模拟数据库操作
     * @param userName
     * @return
     */
    private String getPasswordByUserName(String userName) {

        return userMap.get(userName);
    }
}


编译自定义realm的测试类CustomRealmTest.java

public class CustomRealmTest {

    @Test
    public void testAuthentication(){

        CustomRealm customRealm = new CustomRealm();
        //构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(customRealm);//设置自定义realm


        //设置提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);  //设置环境
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken taken = new UsernamePasswordToken("younghare","123456");
        subject.login(taken);//登录认证数据

        System.out.println("认证的结果是:"+subject.isAuthenticated());
        subject.checkRole("admin");
        subject.checkPermission("user:myadd");//是否具备用户update的权限
    }
}

Shiro加密

shiro散列配置
  • HashedCredentialsMatcher
  • 自定义Realm中使用散列
  • 盐的使用(加盐处理)
Hello shiro基础知识整理---shiro基础篇_第15张图片
调用时为shiro添加加密算法

Hello shiro基础知识整理---shiro基础篇_第16张图片
模拟加密的数据

如果有加盐处理还需要添加盐的处理

Hello shiro基础知识整理---shiro基础篇_第17张图片
shiro加盐处理
Hello shiro基础知识整理---shiro基础篇_第18张图片
认证方法中对加盐设置

自定义realm的加密&加盐CustomRealmJM.java


public class CustomRealmJM extends AuthorizingRealm {
    /*模拟用户的数据库信息*/
    Map userMap = new HashMap<>(16);
    {

        //Md5Hash md5Hash = new Md5Hash("123456");//==e10adc3949ba59abbe56e057f20f883e
        Md5Hash md5Hash = new Md5Hash("123456","younghare");//加盐:younghare处理
        userMap.put("younghare",md5Hash.toString());

        userMap.put("xiaoming","654321");
        super.setName("customRealm");//设置自己的realmName

    }

    @Override //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String userName = (String) principalCollection.getPrimaryPrincipal();
        //从数据库或缓冲中获得角色数据
        Set roles = getRolesByUserName(userName);
        //从数据库或缓冲中获得权限数据
        Set permissions = getPermissionsByUserName(userName);

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

        return simpleAuthorizationInfo;
    }

    /**
     * 模拟用户权限数据
     * @param userName
     * @return
     */
    private Set getPermissionsByUserName(String userName) {
        Set sets = new HashSet<>();
        sets.add("user:myAdd");
        sets.add("user:delete");
        sets.add("user:update");
        return sets;

    }

    /**
     * 模拟角色数据
     * @param userName
     * @return
     */
    private Set getRolesByUserName(String userName) {
        Set sets = new HashSet<>();
        sets.add("admin");
        sets.add("user");
        return sets;
    }

    @Override //认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        /*从主体传来的认证信息中,获得用户名*/
        String userName = (String) authenticationToken.getPrincipal();
        /*通过用户名到数据库中获取凭证*/
        String password = getPasswordByUserName(userName);
        if (password == null){
            return null;
        }

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

        //如果有对shiro加密并加盐了,则需要添加加盐的处理
        authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("younghare"));

        return authenticationInfo;
    }

    /**
     * 模拟数据库操作
     * @param userName
     * @return
     */
    private String getPasswordByUserName(String userName) {
        System.out.println(userName+":"+userMap.get(userName));

        return userMap.get(userName);
    }


}

测试用例的加密&加盐处理CustomRealmJmTest.java


public class CustomRealmJmTest {

    @Test
    public void testAuthentication(){

        CustomRealmJM customRealmJM = new CustomRealmJM();
        //构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(customRealmJM);//设置自定义realm

        /*shiro加密处理*/
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");//设置加密算法的名称
        matcher.setHashIterations(1);//设置加密算法的次数
        customRealmJM.setCredentialsMatcher(matcher);;


        //设置提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);  //设置环境
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken taken = new UsernamePasswordToken("younghare","123456");
        subject.login(taken);//登录认证数据

        System.out.println("认证的结果是:"+subject.isAuthenticated());
/*
        subject.checkRole("admin");
        subject.checkPermission("user:myadd");//是否具备用户update的权限
*/
    }

    @Test  //获取123456的md5值
    public  void testgetMd5(){
        Md5Hash md5Hash = new Md5Hash("123456");
        System.out.println(md5Hash.toString());
    }

    @Test //获取md5加盐
    public  void testgetMd5_jy(){
        //结果值是:b0d6977b961b5f0823a69a4adf9aef80
        Md5Hash md5Hash = new Md5Hash("123456","younghare");
        System.out.println(md5Hash.toString());
    }

}

加盐密码保存的最通用方法是?

拖库本来是数据库领域的术语,指从数据库中导出数据。到了[黑客攻击]泛滥的今天,它被用来指网站遭到入侵后,黑客窃取其数据库。


另开一文Hello shiro+springmvc实例--shiro加强篇

你可能感兴趣的:(Hello shiro基础知识整理---shiro基础篇)