shiro从realm获取安全数据

Realm

realm :域 –存放安全数据的地方。SecurityManager要验证用户的身份,就要从realm获取用户来验证用户的身份是否合法,还需要从realm获取用户的角色和权限来判断用户是否能进行操作。可以把realm看做成一个安全数据源(DataSource)。

实现

需要实现org.apache.shiro.realm.Realm接口

string getName();//返回一个唯一的realm名字
boolean supports(AuthenticationToken token);//由此判断realm是否支持此token
AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)throws AuthenticationException;  //根据Token获取认证信息

单个realm实现

自定义relam实现

public class MyRealm1 implements Realm {
    @Override
    public String getName() {
        return "myrealm1";//返回一个realm名
    }

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

    @Override
    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());
    }
}

在ini 配置文件指定自定义 Realm 实现 (shiro-realm.ini)

[main]
#声明一个realm
myRealm1=org.wct.shiro.realm.MyRealm1
#指定securityManager的realms实现
securityManager.realms=$myRealm1

测试用例如下

    @Test
    public void testShirorealm(){
        //1.得到securityManager并实例化
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
        SecurityManager securityManager = factory.getInstance();
        //2.绑定给SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        //3.得到subject和进行用户身份验证的token
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("zhang","123");
        try{
            subject.login(token);
        }catch (AuthenticationException e){

        }
        Boolean b = subject.isAuthenticated();
        Assert.assertEquals(true,subject.isAuthenticated());//断言用户已经登录
        subject.logout();
    }

多个realm实现

定义myrealm2

public class MyRealm2 implements Realm {
    @Override
    public String getName() {
        return "myrealm2";
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

    @Override
    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String)token.getPrincipal();
        String password = new String((char[]) token.getCredentials());
        if(!"wang".equals(username)){
            throw new UnknownAccountException();
        }
        if (!"123".equals(password)){
            throw new IncorrectCredentialsException();
        }
        return new SimpleAuthenticationInfo(username,password,getName());
    }
}

在ini配置文件里配置(shiro-multi-realm.ini)

[main]
#声明一个realm
myRealm1=org.wct.shiro.realm.MyRealm1
myRealm2=org.wct.shiro.realm.MyRealm2
#指定securityManager的realms实现
securityManager.realms=$myRealm1,$myRealm2

securityManager 会按照 realms 指定的顺序进行身份认证。此处我们使用显示指定顺序的方式指定了 Realm 的顺序,如果删除 “securityManager.realms= m y R e a l m 1 , myRealm2”,那么securityManager 会按照 realm 声明的顺序进行使用(即无需设置 realms 属性,其会自动发现),当我们显示指定 realm 后,其他没有指定 realm 将被忽略,如 “securityManager.realms=$myRealm1”,那么 myRealm2 不会被自动设置进去。

测试代码

@Test
    public void testShiroMultiRealm(){
        //1.得到securityManager并实例化
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro-multi-realm.ini");
        SecurityManager securityManager = factory.getInstance();
        //2.绑定给SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        //3.得到subject和进行用户身份验证的token
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("wang","123");
        try{
            subject.login(token);
        }catch (AuthenticationException e){

        }
        Boolean b = subject.isAuthenticated();
        Assert.assertEquals(true,subject.isAuthenticated());//断言用户已经登录
        subject.logout();
    }

JDBC Realm 使用

数据库及依赖环境

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.25</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>0.2.23</version>
        </dependency>

新建数据库shiro,具体的表和语句参照如下sql

扫描二维码关注公众号,回复: 2482096 查看本文章
drop database if exists shiro;
create database shiro;
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');

配置文件ini(shiro-jdbc-realm)

jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro
dataSource.username=root
dataSource.password=*****
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm

测试类代码如下:

    @Test
    public void testShiroJdbcRealm(){
        //1.得到securityManager并实例化
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");
        SecurityManager securityManager = factory.getInstance();
        //2.绑定给SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        //3.得到subject和进行用户身份验证的token
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("zhang","123");
        try{
            subject.login(token);
        }catch (AuthenticationException e){

        }
        Boolean b = subject.isAuthenticated();
        Assert.assertEquals(true,subject.isAuthenticated());//断言用户已经登录
        subject.logout();
    }

猜你喜欢

转载自blog.csdn.net/cijiancao/article/details/80989401
今日推荐