我的成长磨练,每天写博客,年轻人,卷起袖子,来把手弄脏吧! ------ 博客首页

shiro权限的认证及shiro的配置

一.使用shiro框架需要引入的依赖

<!--引入shiro的依赖-->
  <!-- shiro start -->
    <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>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.6</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.6</version>
    </dependency>

2.配置ini文件(代替数据库)

    ini文件确定了数据库的认证规则

# 配置自定义的realm(自定义数据库认证规则)
[main]
# 配置加密认证的凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName=MD5
credentialsMatcher.hashIterations=2

myRealm=com.woniu.shiro.realm.md5.authorization.AuthenticationAuthorizationMD5Realm
myRealm.credentialsMatcher=$credentialsMatcher
securityManager.realms=$myRealm

3.配置Realm的Java代码

package com.woniu.shiro.realm.authorization;

import java.util.HashSet;
import java.util.Set;

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;

/**
 *     自定义认证、授权规则 【数据库校验】
 */
@SuppressWarnings("all")
public class AuthenticationAuthorizationRealm extends AuthorizingRealm{

    //1. 认证规则
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //1. principal 身份信息【账号, 用户对象】
        Object principal = token.getPrincipal();
        //2.  真实开发要使用这个身份去数据库查询该账号是否存在
        if (!"admin".equals(principal))  // 模拟数据库只有一个admin账号
            return null;  //自动被UnknownAccountException捕获【账号不存在】
        //3.credentials 真实数据库凭证 【就是账号对应的数据库密码】
        Object credentials = "123";
        //14. 构建一个 AuthenticationInfo 认证信息对象
        SimpleAuthenticationInfo authenticationInfo = 
                new SimpleAuthenticationInfo(principal, credentials, getName());
        /**
         *     将真实凭证credentials  与  token中的password进行equals()比较: 
         *         相同  : 就返回authenticationInfo
         *         不相同: 抛出IncorrectCredentialsException  [密码错误]
         */
        return authenticationInfo;
    }
    
    //2. 授权规则(最终授予的是角色对应的权限)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //1. 需要获取到认证成功的身份
        Object principal = principals.getPrimaryPrincipal();
        //2. 查询权限 ;[开发中应该 : principal去查此身份对应的角色,通过角色再查询角色对应的权限【返回的是该身份所对应的权限集合】]
        Set<String> permissions = new HashSet<String>(); // 模拟一个数据库的权限查询结果
        permissions.add("user:*");
        permissions.add("item:select");
        permissions.add("item:update");
        permissions.add("item:insert");
        //3. 构建一个 AuthorizationInfo 授权信息对象
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setStringPermissions(permissions); // 授权
        return authorizationInfo;
    }

}

Realm的工作原理:

       1.根据subject.login(token)可以将token传到myrealm的认证方法里

  2.从token中得到用户传来的用户账号和密码

  3.根据用户的账号从数据库查找该用户,不存在则返回null

  4.若用户存在则需要得到用户的密码,构建一个认证信息的对象 authenticationInfo = new SimpleAuthenticationInfo(待认证对象,数据库的密码,当前realm对象)

  5.将数据库的密码与token中的密码进行equals判断,相同则return authenticationInfo 不同则 throw new IncorrectCredentialsException()

4.测试代码

package com.woniu.shiro.realm.authorization;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;

/**
 *     通过读取配置文件info.ini来完成shior认证
 *         SecurityManager: 管理认证和授权
 * 
 *      【 认证 】: 将subject用户校验【前端form】的账号、密码与info.ini配置文件中的账号/密码进行比对
*/
@SuppressWarnings("all")
public class ShiroAuthenticationAuthorizationTest {
    public static void main(String[] args) {
        //1. 创建Shiro安全管理工厂
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:info_realm_authorization.ini");
        //2. 从工厂中创建出SecurityManager安全管理对象
        SecurityManager securityManager = factory.getInstance();
        //3. 将安全管理对象与shior环境绑定
        SecurityUtils.setSecurityManager(securityManager);
        //4. 创建待校验的subject(用户)
        Subject subject = SecurityUtils.getSubject();
        //5.创建账号密码令牌 【token : 令牌】
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "123");
        //6.开始认证
        try {
            subject.login(token);  // 登录验证
        }catch (UnknownAccountException e) { // UnknownAccountException 未知的账号异常
            System.out.println("用户名不存在");
        }catch (IncorrectCredentialsException e) { // IncorrectCredentialsException 不正确的凭证异常
            System.out.println("密码错误");
        }catch (AuthenticationException e) {  // AuthenticationException 认证异常
            System.out.println("未知错误");
        }
        //7.认证是否通过的判断条件
        System.out.println("认证的结果 : " + subject.isAuthenticated());
        if(!subject.isAuthenticated())
            return;
        //8.判断此身份具有哪些体统操作的权限
        System.out.println("用户添加权限:"+subject.isPermitted("user:insert"));
        System.out.println("用户删除权限:"+subject.isPermitted("user:delete"));
        System.out.println("用户修改权限:"+subject.isPermitted("user:update"));
        System.out.println("用户查询权限:"+subject.isPermitted("user:select"));
        System.out.println("-----------------------------------------");
        System.out.println("商品添加权限:"+subject.isPermitted("item:insert"));
        System.out.println("商品删除权限:"+subject.isPermitted("item:delete"));
        System.out.println("商品修改权限:"+subject.isPermitted("item:update"));
        System.out.println("商品查询权限:"+subject.isPermitted("item:select"));
        
    }
}

 

shiro底层执行流程

1.利用IniSecurityManagerFactory加载配置文件并创建工厂(factory) =>

2.利用工厂创建安全管理对象(securityManager=factory.getInstance()) =>

3.将安全管理对象与shiro环境绑定SecurityUtils.setSecurityManager(securityManager)=>

4.创建待校验的subject(用户) =>

5. 创建账号的密码令牌new UsernamePasswordToken("前端账号","前端密码") =>

6.进行校验subject.login(token);

 

shiro的认证流程

首先根据配置文件创建安全管理工厂factor =new  iniSecurityManagerFactory("classpath:配置文件名称")  ==>

再通过工厂创建安全管理对象manager = factory.getInstance() ==>

之后将对象与shiro绑定 SecurityUtils.setSecurityManager(securityManager) ==>

得到subject对象SecurityUtils.getSubject()==>

创建用户token  = new UsernamePasswordToken("用户账号","用户密码") ==>

subject.login(token)==>

会将token'传给realm,在realm中得到token并将token中的账号取出来 ==>

通过账号从数据库查询user,用数据库查询出来的user的密码与token中的密码比对 ==>

根据结果返回相应的行为;

 

posted @ 2020-07-20 22:26  Loginout  阅读(488)  评论(0编辑  收藏  举报

web应用开发&研究 - 创建于 2014年8月17日

这是一位web前端开发工程师的个人站,内容主要是网站开发方面的技术文章,大部分来自学习或工作,部分来源于网络,希望对大家有所帮助。

致力于web应用开发&研究工作,专注web前端开发,关注互联网前沿技术与趋势。


Font Awesome | Respond.js | Bootstrap中文网