多realm以及jdbcRealm配置

Posted zailushang1996

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多realm以及jdbcRealm配置相关的知识,希望对你有一定的参考价值。

多realm配置

public class MyRealm1 implements Realm {


    public String getName() {
        return "myrealm1";
    }
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken; //仅支持UsernamePasswordToken类型的Token
    }
    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 class MyRealm2 implements Realm {


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


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


    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(); //如果密码错误
        }
        //如果身份认证验证成功,返回一个AuthenticationInfo实现;
        return new SimpleAuthenticationInfo(username, password, getName());
    }
}

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

securityManege会按照realm指定顺序进行身份验证,没有指定(securityManager.realms=myRealm1,myRealm2)也可以,那就会按照申明顺序进行使用。当显示指定realm后,其他没有被指定realm会被忽略,如:securityManage.realms=$myRealm1,那么myRealm2就不会被设置进realms。

@Test
    public void testCustomMultiRealm() {
        //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
        Factory<org.apache.shiro.mgt.SecurityManager> factory =
                new IniSecurityManagerFactory("classpath:shiro-multi-realm.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("wang", "123");

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

        Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录

        //6、退出
        subject.logout();
    }

jdbcRealm使用

[main]
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=root
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm

测试代码同上

问题记录:

当使用身份凭证登录后,再获取token信息时,如何设置token中放置的内容?

查看JdbcRealm类源码,可以看到doGetAuthenticationInfo(AuthenticationToken token)方法返回一个SimpleAuthenticationInfo info= new SimpleAuthenticationInfo(username, password.toCharArray(), this.getName());故而token中只放了username。

下面这个自定义realm类,在内部查询数据库,综合了自定义realm与jdbcRealm。

public class SampleRealm extends AuthorizingRealm {

    @Autowired
    UUserService userService;
    @Autowired
    PermissionService permissionService;
    @Autowired
    RoleService roleService;

    public SampleRealm() {
        super();
    }

    /**
     * 认证信息,主要针对用户登录,
     */
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authcToken) throws AuthenticationException {

        ShiroToken token = (ShiroToken) authcToken;
        UUser user = userService.login(token.getUsername(), token.getPswd());
        if (null == user) {
            throw new AccountException("帐号或密码不正确!");
            /**
             * 如果用户的status为禁用。那么就抛出<code>DisabledAccountException</code>
             */
        } else if (UUser._0.equals(user.getStatus())) {
            throw new DisabledAccountException("帐号已经禁止登录!");
        } else {
            //更新登录时间 last login time
            user.setLastLoginTime(new Date());
            userService.updateByPrimaryKeySelective(user);
        }
        return new SimpleAuthenticationInfo(user, user.getPswd(), getName());
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        Long userId = TokenManager.getUserId();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //根据用户ID查询角色(role),放入到Authorization里。
        Set<String> roles = roleService.findRoleByUserId(userId);
        info.setRoles(roles);
        //根据用户ID查询权限(permission),放入到Authorization里。
        Set<String> permissions = permissionService.findPermissionByUserId(userId);
        info.setStringPermissions(permissions);
        return info;
    }

    /**
     * 清空当前用户权限信息
     */
    public void clearCachedAuthorizationInfo() {
        PrincipalCollection principalCollection = SecurityUtils.getSubject().getPrincipals();
        SimplePrincipalCollection principals = new SimplePrincipalCollection(
                principalCollection, getName());
        super.clearCachedAuthorizationInfo(principals);
    }

    /**
     * 指定principalCollection 清除
     */
    public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) {
        SimplePrincipalCollection principals = new SimplePrincipalCollection(
                principalCollection, getName());
        super.clearCachedAuthorizationInfo(principals);
    }
}

关键点:doGetAuthenticationInfo(AuthenticationToken token)方法的返回值

return new SimpleAuthenticationInfo(user, user.getPswd(), getName());所以返回的token是一个user实体。

以上是关于多realm以及jdbcRealm配置的主要内容,如果未能解决你的问题,请参考以下文章

shiro之 JdbcRealm及Authentication Strategy

Tomcat使用JDBC Realm配置Basic认证

shiro自定义realm

shiro学习笔记_0600_自定义realm实现授权

shiro,使用第三方jdbcRealm连接数据库操作

shiro-web-02