(3)shiro自定义realm

上面一章说到shiro的认证和授权最底层就是调用realm的getAuthorizationInfo(获取用户的角色和资源)和getAuthenticationInfo(校验账号密码是否正确)两个方法。

如果我们要从数据库中查询用户和他的权限信息,我们可以使用shiro提供给我们的JdbcRealm

 JdbcRealm

 添加jar

<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>

classpath环境下新建shiro-jdbc.ini如下配置
这里我们采用了阿里巴巴的数据源,注入到jdbcRealm的dataSource变量中,并且将这个jdbcRealm注入到securityManager,有点类似于spring的注入。

下面的sql放在github上对应的章节根目录下,导入即可,数据库密码填写自己数据库密码

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=123456
jdbcRealm.dataSource=$dataSource
#注入securityManager的realm
securityManager.realms=$jdbcRealm

测试代码:

ShiroUtils.login("classpath:shiro-jdbc.ini","zhang","123456");
Subject subject = SecurityUtils.getSubject();
//是否通过认证
System.out.println(subject.isAuthenticated());

 

其中ShiroUtils的登录方法(这个以后直接略过):

    public static void login(String configPath,String username,String password){
        Factory<SecurityManager> factory =new IniSecurityManagerFactory(configPath);
        //得到安全管理器
        SecurityManager securityManager = factory.getInstance();

        SecurityUtils.setSecurityManager(securityManager);

        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(username, password);


        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
    }
View Code

 

 

最后输出true。

因为jdbcRealm里面的sql都是固定的,所以我们表结构都要按照JdbcRealm里面创建对应的表。下面是JdbcRealm里面各种查询的sql(salt是密码加密,后面介绍加密再说,我们这里直接用明文密码)

表里面数据分别如下

 

接着测试代码添加如下:

        System.out.println(subject.hasRole("role1"));

        System.out.println(subject.isPermitted("user:create"));

 

最后输出true,false

为什么角色role1获取到了,permission没有获取到呢。

 

原因是JdbcRealm里面有个permissionsLookupEnabled默认是false,所以不会查询对应的资源权限,我们在配置文件中打开这个查询。

#打开permission查询
jdbcRealm.permissionsLookupEnabled=true

 

再查询就是true了。

 

自定义Realm

1 新增MyRealm类直接继承AuthorizingRealm.

public class MyRealm extends AuthorizingRealm {

    //认证信息,
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        String username = upToken.getUsername();
        String password = new String(upToken.getPassword());
        //模拟用户名密码是否正确
        if(!"zhang".equals(username)){
           throw new UnknownAccountException();
        }
        if(!"123456".equals(password)){
            throw new IncorrectCredentialsException();
        }
        return new SimpleAuthenticationInfo(username,password,getName());

    }

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获取用户名
        String username = (String)getAvailablePrincipal(principals);
        //模拟从数据库查询出来对应的角色和权限
        Set<String> roles = new HashSet<String>();
        roles.add("role_1");
        roles.add("role_2");

        Set<String> permissions = new HashSet<String>();
        permissions.add("user:create");
        permissions.add("user:delete");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setRoles(roles);
        info.setStringPermissions(permissions);
        return info;
    }


}

2,classpath文件下新建shiro-myrealm.ini配置文件

myrealm= com.nfcm.shiro.Realm.MyRealm
securityManager.realms=$myrealm

3,测试

        ShiroUtils.login("classpath:shiro-myrealm.ini","zhang","123456");

        Subject subject = SecurityUtils.getSubject();
        //是否通过认证
        System.out.println(subject.isAuthenticated());
        //是否有role1角色
        System.out.println(subject.hasRole("role_1"));

        System.out.println(subject.isPermitted("user:create"));

 

到这里全部测试通过。

 

github代码地址

https://github.com/cmniefei/shiroparent

 

posted @ 2018-11-01 14:30  nfcm  阅读(811)  评论(0编辑  收藏  举报