shiro的认证和授权

shiro的认证和授权

导依赖

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
</dependency>

shiro中的md5加盐散列

shiro框架认为单纯的md5加密不是很安全,所以可以引入shiro的Md5Hash,即md5哈希散列

public static void main(String[] args) {
    
    
        Md5Hash md5Hash = new Md5Hash();
        //不要用set进行赋值,错误!!!!
        md5Hash.setBytes("123".getBytes());
        System.out.println(md5Hash.toHex());
        //应该在构造方法中进行加密,正确!!!!
        //此时就是默认的md5,并没有进行散列
        Md5Hash md5Hash1 = new Md5Hash("123321");
        System.out.println(md5Hash1.toHex());
        //此时是加盐加hash散列的md5算法
        Md5Hash md5Hash2 = new Md5Hash("123321", "pf@5", 1024);
        System.out.println(md5Hash2.toHex());
    }

shiro的简单认证练习

在resource中创建shiro.ini文件(方便测试)

[users]
if=123321

随便创建一个HelloWorld.java文件,在main方法中写下

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
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;

/**
 * @Author if
 * @Description: What is it
 * @Date 2021-02-08 下午 03:27
 */
public class HelloWorld {
    
    
    public static void main(String[] args) {
    
    
        //1.创建安全管理器对象
        DefaultSecurityManager securityManager=new DefaultSecurityManager();
        //2.给安全管理器设置realm
        securityManager.setRealm(new IniRealm("classpath:shiro.ini"));
        //3.SecurityUtils给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(securityManager);
        //4.关键对象Subject主体
        Subject subject=SecurityUtils.getSubject();
        //5.创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken("if","123321");
        try{
    
    
            System.out.println("认证状态:"+(subject.isAuthenticated()?"认证成功":"还未认证"));
            subject.login(token);
            System.out.println("认证状态:"+(subject.isAuthenticated()?"认证成功":"还未认证"));
        }catch(UnknownAccountException e){
    
    
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
    
    
            System.out.println("密码错误");
        }
    }
}

自定义realm类

由于为了方便,使用了jdbc作为数据库连接

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 org.apache.shiro.util.ByteSource;

import java.sql.*;

/**
 * @Author if
 * @Description: 自定义realm实现,将认证/授权数据的来源转为数据库的实现
 * @Date 2021-02-08 下午 10:53
 */
public class CustomerRealm extends AuthorizingRealm {
    
    
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    
    
        //身份信息(其实就是用户名等)
        String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
        System.out.println(primaryPrincipal+"访问了doGetAuthorizationInfo()方法");
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //其实这里应该是放数据库中对应的权限角色(一个账号可以有多个角色),懒得去新加字段然后连接了
        simpleAuthorizationInfo.addRole("user");
        simpleAuthorizationInfo.addRole("admin");
        return simpleAuthorizationInfo;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    
    
        //获取身份信息(手机号/邮箱等)
        String username= (String) authenticationToken.getPrincipal();
        //根据身份信息使用jdbc查询数据库
        try {
    
    
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection("jdbc:mysql:///test1", "root", "数据库密码");
            String sql = "select * from t_user where uname=?";
            PreparedStatement ptmt = conn.prepareStatement(sql);
            ptmt.setString(1,username);
            ResultSet rs = ptmt.executeQuery();
            //因为查询出来的头指针指向null,需要先next一下才能指向第一个结果
            rs.next();
            System.out.println("数据库中\n"+rs.getString("uname")+" ---- "+rs.getString("pwd"));
            //进行判断
            if(rs.getString("uname").equals(username)){
    
    
                /**
                 * 传入3个参数
                 * 1.数据库中正确的用户名
                 * 2.数据库中正确的密码
                 * 3.(可选)若有加盐则填入盐(盐一般写入数据库中,每个用户都可以不同,ByteSource.Util.bytes("盐")即可  )
                 * 4.当前的realm信息(根据this.getName()获得)
                 */
                SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(rs.getString("uname"),rs.getString("pwd"), ByteSource.Util.bytes(rs.getString("salt")),this.getName());
                conn.close();
                ptmt.close();
                rs.close();
                return simpleAuthenticationInfo;
            }
        } catch (Exception e) {
    
    
            return null;
        }
        return null;
    }
}

自定义realm实现shiro的认证和授权

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
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 java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Author if
 * @Description: 使用自定义realm实现 认证授权数据源于数据库
 * @Date 2021-02-08 下午 10:58
 */
public class TestCustomerRealm {
    
    
    public static void main(String[] args) {
    
    
        //1.创建安全管理器对象
        DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
        //2.new自定义realm
        CustomerRealm customerRealm = new CustomerRealm();
        //3.设置加md5、加hash散列加密方式配置(加盐配置在CustomerRealm类中写)
        HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(1024);
        customerRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        //4.给安全管理器设置自定义的realm
        defaultSecurityManager.setRealm(customerRealm);
        //5.SecurityUtils给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //6.关键对象Subject主体
        Subject subject=SecurityUtils.getSubject();
        //7.创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken("Tom","123321");
        try{
    
    
            System.out.println("认证状态:"+(subject.isAuthenticated()?"认证成功":"还未认证"));
            subject.login(token);
            System.out.println("认证状态:"+(subject.isAuthenticated()?"认证成功":"还未认证"));
        }catch(UnknownAccountException e){
    
    
            System.out.println("用户名错误");
            /**
             * 未进行md5加密时报IncorrectCredentialsException异常
             * IncorrectCredentialsException是AuthenticationException子类
             * 所以通用的话写AuthenticationException为好
             */
        } catch (AuthenticationException e){
    
    
            System.out.println("密码错误");
        }

        //测试授权
        if(subject.isAuthenticated()){
    
    
            //基于角色权限控制,判断几个权限就访问几次doGetAuthorizationInfo方法
            //判断单个权限
            System.out.println("是否具有admin权限:"+(subject.hasRole("admin")?"有":"没有"));
            //判断任意一权限(或)
            System.out.println("是否具有admin、user、super其中一个:");
            List list=new ArrayList();
            list.add("admin");
            list.add("user");
            list.add("super");
            int i=0;
            for (boolean b : subject.hasRoles(list)) {
    
    
                System.out.println("是否具有"+list.get(i)+": "+(b?"具有":"没有"));
                i++;
            }
            //判断是否同时具有所有权限(且)
            System.out.println("是否同时具有admin和user:"+(subject.hasAllRoles(Arrays.asList("admin","user"))?"同时具有":"不是同时具有"));
        }
    }
}

结果

认证状态:还未认证
数据库中
Tom ---- 7615a154b34f0a31f225dcfc681acbfc
认证状态:认证成功
Tom访问了doGetAuthorizationInfo()方法
是否具有admin权限:有
是否具有admin、user、super其中一个:
Tom访问了doGetAuthorizationInfo()方法
Tom访问了doGetAuthorizationInfo()方法
Tom访问了doGetAuthorizationInfo()方法
是否具有admin: 具有
是否具有user: 具有
是否具有super: 没有
Tom访问了doGetAuthorizationInfo()方法
Tom访问了doGetAuthorizationInfo()方法
是否同时具有admin和user:同时具有

Guess you like

Origin blog.csdn.net/Jay_Chou345/article/details/113765308