Shiro学习笔记(四)--- CustomRealm

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/EndTheme_Xin/article/details/83862667

一、简介

CustomRealm(自定义Realm)是通过仿造JdbcRealm,继承AuthrizingRealm,

重写doGetAuthenticationInfo(AuthenticationToken token)【认证】和 doGetAuthorizationInfo(PrincipalCollection principalCollection)【授权】方法

二、理解

自定义的Realm,主要注意一下几个步骤:

  1. 首先继承并实现类AuthorizingRealm的方法。其中方法

    doGetAuthenticationInfo 主要做认证操作,即可以通过获取其中的

    用户名,查询出相应的密码,然后将用户名与密码一并返回,shiro会自动根据传入的用户名与密码与此Realm返回的用户名和密码作比对,返回你想要的结果。同理doGetAuthorizationInfo主要是用来做角色与权限的验证,也是通过用户名,从数据库中查找到相应的角色或者权限的数据并返回一个Simple的授权类,授权系统会根据传入的参数与返回的结果集对比,存在返回true不存在则抛异常。

  2. 两者方法只能获取用户名称,通过用户名称连接数据库获取其他信息。这里只是做数据准备操作,并不做判断是否传入的值与其相符的操作,此操作在此之后进行。

  3. 根据两者的返回对象分别返回Simple类型的对象。认证的对象需要将你获取的用户名和密码放到构造方法中。授权的对象需要你set到相应的方法中。

三、代码(参考官方JdbcRealm的实现)

public class JdbcRealm extends AuthorizingRealm {
    protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
    protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";
    protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";
    protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";
    private static final Logger log = LoggerFactory.getLogger(JdbcRealm.class);
    protected DataSource dataSource;
    protected String authenticationQuery = "select password from users where username = ?";
    protected String userRolesQuery = "select role_name from user_roles where username = ?";
    protected String permissionsQuery = "select permission from roles_permissions where role_name = ?";
    protected boolean permissionsLookupEnabled = false;
    protected JdbcRealm.SaltStyle saltStyle;

    public JdbcRealm() {
        this.saltStyle = JdbcRealm.SaltStyle.NO_SALT;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void setAuthenticationQuery(String authenticationQuery) {
        this.authenticationQuery = authenticationQuery;
    }

    public void setUserRolesQuery(String userRolesQuery) {
        this.userRolesQuery = userRolesQuery;
    }

    public void setPermissionsQuery(String permissionsQuery) {
        this.permissionsQuery = permissionsQuery;
    }

    public void setPermissionsLookupEnabled(boolean permissionsLookupEnabled) {
        this.permissionsLookupEnabled = permissionsLookupEnabled;
    }

    public void setSaltStyle(JdbcRealm.SaltStyle saltStyle) {
        this.saltStyle = saltStyle;
        if (saltStyle == JdbcRealm.SaltStyle.COLUMN && this.authenticationQuery.equals("select password from users where username = ?")) {
            this.authenticationQuery = "select password, password_salt from users where username = ?";
        }

    }

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken)token;
        String username = upToken.getUsername();
        if (username == null) {
            throw new AccountException("Null usernames are not allowed by this realm.");
        } else {
            Connection conn = null;
            SimpleAuthenticationInfo info = null;

            try {
                String salt;
                try {
                    conn = this.dataSource.getConnection();
                    String password = null;
                    salt = null;
                    switch(this.saltStyle) {
                    case NO_SALT:
                        password = this.getPasswordForUser(conn, username)[0];
                        break;
                    case CRYPT:
                        throw new ConfigurationException("Not implemented yet");
                    case COLUMN:
                        String[] queryResults = this.getPasswordForUser(conn, username);
                        password = queryResults[0];
                        salt = queryResults[1];
                        break;
                    case EXTERNAL:
                        password = this.getPasswordForUser(conn, username)[0];
                        salt = this.getSaltForUser(username);
                    }

                    if (password == null) {
                        throw new UnknownAccountException("No account found for user [" + username + "]");
                    }

                    info = new SimpleAuthenticationInfo(username, password.toCharArray(), this.getName());
                    if (salt != null) {
                        info.setCredentialsSalt(Util.bytes(salt));
                    }
                } catch (SQLException var12) {
                    salt = "There was a SQL error while authenticating user [" + username + "]";
                    if (log.isErrorEnabled()) {
                        log.error(salt, var12);
                    }

                    throw new AuthenticationException(salt, var12);
                }
            } finally {
                JdbcUtils.closeConnection(conn);
            }

            return info;
        }
    }

    private String[] getPasswordForUser(Connection conn, String username) throws SQLException {
        boolean returningSeparatedSalt = false;
        String[] result;
        switch(this.saltStyle) {
        case NO_SALT:
        case CRYPT:
        case EXTERNAL:
            result = new String[1];
            break;
        case COLUMN:
        default:
            result = new String[2];
            returningSeparatedSalt = true;
        }

        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            ps = conn.prepareStatement(this.authenticationQuery);
            ps.setString(1, username);
            rs = ps.executeQuery();

            for(boolean foundResult = false; rs.next(); foundResult = true) {
                if (foundResult) {
                    throw new AuthenticationException("More than one user row found for user [" + username + "]. Usernames must be unique.");
                }

                result[0] = rs.getString(1);
                if (returningSeparatedSalt) {
                    result[1] = rs.getString(2);
                }
            }
        } finally {
            JdbcUtils.closeResultSet(rs);
            JdbcUtils.closeStatement(ps);
        }

        return result;
    }

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        if (principals == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        } else {
            String username = (String)this.getAvailablePrincipal(principals);
            Connection conn = null;
            Set<String> roleNames = null;
            Set permissions = null;

            try {
                conn = this.dataSource.getConnection();
                roleNames = this.getRoleNamesForUser(conn, username);
                if (this.permissionsLookupEnabled) {
                    permissions = this.getPermissions(conn, username, roleNames);
                }
            } catch (SQLException var11) {
                String message = "There was a SQL error while authorizing user [" + username + "]";
                if (log.isErrorEnabled()) {
                    log.error(message, var11);
                }

                throw new AuthorizationException(message, var11);
            } finally {
                JdbcUtils.closeConnection(conn);
            }

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

    protected Set<String> getRoleNamesForUser(Connection conn, String username) throws SQLException {
        PreparedStatement ps = null;
        ResultSet rs = null;
        LinkedHashSet roleNames = new LinkedHashSet();

        try {
            ps = conn.prepareStatement(this.userRolesQuery);
            ps.setString(1, username);
            rs = ps.executeQuery();

            while(rs.next()) {
                String roleName = rs.getString(1);
                if (roleName != null) {
                    roleNames.add(roleName);
                } else if (log.isWarnEnabled()) {
                    log.warn("Null role name found while retrieving role names for user [" + username + "]");
                }
            }
        } finally {
            JdbcUtils.closeResultSet(rs);
            JdbcUtils.closeStatement(ps);
        }

        return roleNames;
    }

    protected Set<String> getPermissions(Connection conn, String username, Collection<String> roleNames) throws SQLException {
        PreparedStatement ps = null;
        LinkedHashSet permissions = new LinkedHashSet();

        try {
            ps = conn.prepareStatement(this.permissionsQuery);
            Iterator var6 = roleNames.iterator();

            while(var6.hasNext()) {
                String roleName = (String)var6.next();
                ps.setString(1, roleName);
                ResultSet rs = null;

                try {
                    rs = ps.executeQuery();

                    while(rs.next()) {
                        String permissionString = rs.getString(1);
                        permissions.add(permissionString);
                    }
                } finally {
                    JdbcUtils.closeResultSet(rs);
                }
            }
        } finally {
            JdbcUtils.closeStatement(ps);
        }

        return permissions;
    }

    protected String getSaltForUser(String username) {
        return username;
    }

    public static enum SaltStyle {
        NO_SALT,
        CRYPT,
        COLUMN,
        EXTERNAL;

        private SaltStyle() {
        }
    }
}

猜你喜欢

转载自blog.csdn.net/EndTheme_Xin/article/details/83862667
今日推荐