30、shiro框架入门2,关于Realm

1、Jdbc的Realm链接,并且获取权限

首先创建shiro-jdbc.ini的配置文件,主要配置链接数据库的信息

配置文件中的内容如下所示

1、变量名=全限定类名会自动创建一个类实例

2、变量名.属性=值 自动调用相应的setter方法进行赋值

3、$变量名 引用之前的一个对象实例 

4、测试代码请参照com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest的testJDBCRealm方法,和之前的没什么区别。

 

 

  到数据库shiro下建三张表:users(用户名/密码)、user_roles(用户/角色)、roles_permissions(角色/权限),具体请参照shiro-example-chapter2/sql/shiro.sql;并添加一个用户记录,用户名/密码为zhang/123;

复制代码
USE shiro;

CREATE TABLE users (
  id BIGINT AUTO_INCREMENT,
  username VARCHAR(100),
  PASSWORD VARCHAR(100),
  password_salt VARCHAR(100),
  CONSTRAINT pk_users PRIMARY KEY(id)
) CHARSET=utf8 ENGINE=INNODB;
CREATE UNIQUE INDEX idx_users_username ON users(username);

CREATE TABLE user_roles(
  id BIGINT AUTO_INCREMENT,
  username VARCHAR(100),
  role_name VARCHAR(100),
  CONSTRAINT pk_user_roles PRIMARY KEY(id)
) CHARSET=utf8 ENGINE=INNODB;
CREATE UNIQUE INDEX idx_user_roles ON user_roles(username, role_name);

CREATE TABLE roles_permissions(
  id BIGINT AUTO_INCREMENT,
  role_name VARCHAR(100),
  permission VARCHAR(100),
  CONSTRAINT pk_roles_permissions PRIMARY KEY(id)
) CHARSET=utf8 ENGINE=INNODB;
CREATE UNIQUE INDEX idx_roles_permissions ON roles_permissions(role_name, permission);

INSERT INTO users(username,PASSWORD)VALUES('zhang','123');
复制代码

 

然后就是单元测试的过程,java通过读取realm-jdbc.ini文件获取权限,角色,用户名称等

复制代码
@Test
    public void testJDBCRealm() {
        //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
        Factory<org.apache.shiro.mgt.SecurityManager> factory =
                new IniSecurityManagerFactory("classpath:shiro-jdbc.ini");
        //2、得到SecurityManager实例 并绑定给SecurityUtils
        org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
      //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");

        try {
            //4、登录,即身份验证
            subject.login(token);
        } catch (AuthenticationException e) {
        }

        Assert.assertEquals(true, subject.isAuthenticated()); 
        //6、退出
        subject.logout();
    }
复制代码

二、

Authenticator及AuthenticationStrategy

Authenticator的职责是验证用户帐号,是Shiro API中身份验证核心的入口点: 

public AuthenticationInfo authenticate(AuthenticationToken authenticationToken)
            throws AuthenticationException;&nbsp;

如果验证成功,将返回AuthenticationInfo验证信息;此信息中包含了身份及凭证;如果验证失败将抛出相应的AuthenticationException实现。

SecurityManager接口继承了Authenticator,另外还有一个ModularRealmAuthenticator实现,其委托给多个Realm进行验证,验证规则通过AuthenticationStrategy接口指定,默认提供的实现:

FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略;

AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份验证成功的认证信息;

AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。

ModularRealmAuthenticator默认使用AtLeastOneSuccessfulStrategy策略。

 

复制代码
[main]

#指定securityManager的authenticator实现  
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator  
securityManager.authenticator=$authenticator  
#指定securityManager.authenticator的authenticationStrategy  
allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy  
securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy
myRealm1=realm.MyRealm1  
myRealm2=realm.MyRealm2
securityManager.realms=$myRealm1,$myRealm2 
复制代码

 

复制代码
package realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.realm.Realm;

public class MyRealm2 implements Realm{

    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        String username=(String)token.getPrincipal();//得到用户名
        String password=new String((char[])token.getCredentials());//得到密码
        if(!"zhang".equals(username)){
            throw new UnknownAccountException();//如果用户名错误
        }
        if(!"123".equals(password)){
            throw new IncorrectCredentialsException();//如果密码错误
        }
        //如果身份认证成功,返回一个AuthenticationInfo实现;
        return new SimpleAuthenticationInfo("zhang@163.com", "123", getName());
    }

    public String getName() {
        return "myrealm2";
    }

    public boolean supports(AuthenticationToken token) {
        //仅支持UsernamePasswordToken类型的Token  
        return token instanceof UsernamePasswordToken;
    }

}
复制代码

 

复制代码
package realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.realm.Realm;

public class MyRealm1 implements Realm{

    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        String username=(String)token.getPrincipal();//得到用户名
        String password=new String((char[])token.getCredentials());//得到密码
        if(!"zhang".equals(username)){
            throw new UnknownAccountException();//如果用户名错误
        }
        if(!"123".equals(password)){
            throw new IncorrectCredentialsException();//如果密码错误
        }
        //如果身份认证成功,返回一个AuthenticationInfo实现;
        return new SimpleAuthenticationInfo(username, password, getName());
    }

    public String getName() {
        return "myrealm1";
    }

    public boolean supports(AuthenticationToken token) {
        //仅支持UsernamePasswordToken类型的Token  
        return token instanceof UsernamePasswordToken;
    }

}
复制代码

 

 

 

1
2
3
4
5
6
7
8
@Test
    public void testMoreAuthention() {
        login("classpath:shiro-authenticator-all-success.ini");
        Subject subject = SecurityUtils.getSubject(); 
         //得到一个身份集合,其包含了Realm验证成功的身份信息
        PrincipalCollection collection=subject.getPrincipals();
        Assert.assertEquals(2, collection.asList().size());
    }

  最后测试好像不太好使

login方法

复制代码
public void login(String config){
        System.out.println(config);
        Factory<org.apache.shiro.mgt.SecurityManager> factory=
                new IniSecurityManagerFactory(config);
        org.apache.shiro.mgt.SecurityManager manager = (org.apache.shiro.mgt.SecurityManager) factory.getInstance();
        SecurityUtils.setSecurityManager(manager);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
        subject.login(token);
    }
复制代码

 

posted @   香港胖仔  阅读(678)  评论(1编辑  收藏  举报
编辑推荐:
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
阅读排行:
· 官方的 MCP C# SDK:csharp-sdk
· 一款 .NET 开源、功能强大的远程连接管理工具,支持 RDP、VNC、SSH 等多种主流协议!
· 提示词工程师自白:我如何用一个技巧解放自己的生产力
· 一文搞懂MCP协议与Function Call的区别
· 如何不购买域名在云服务器上搭建HTTPS服务
点击右上角即可分享
微信分享提示