Cas(06)——基于数据库的认证

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 基于数据库的认证   目录 1.1      BindModeSearchDatabaseAuthenticationHandler 1.2      QueryDatabaseAuthenticationHandler 1.

基于数据库的认证

 

目录

1.1      BindModeSearchDatabaseAuthenticationHandler

1.2      QueryDatabaseAuthenticationHandler

1.2.1     PrefixSuffixPrincipalNameTransformer

1.2.2     DefaultPasswordEncoder

1.3      SearchModeSearchDatabaseAuthenticationHandler

 

       Cas Server自身已经为我们实现了几种基于JDBCAuthenticationHandler实现,但它们不包含在Cas Server的核心包里面,而是包含在cas-server-support-jdbc中,如果我们要使用Cas Server已经实现好的基于JDBCAuthenticationHandler,我们必须先将cas-server-support-jdbc对应的jar包、相关数据库的驱动,以及所需要使用的数据源实现等jar包加入Cas Server的类路径中。如果是基于Mavenwar覆盖机制来修改Cas Server的配置文件,则我们可以在自己的Maven项目的依赖中加入如下项(对应的驱动就没贴出来了)。

      <dependency>

         <groupId>org.jasig.cas</groupId>

         <artifactId>cas-server-support-jdbc</artifactId>

         <version>${cas.version}</version>

         <scope>runtime</scope>

      </dependency>

 

       Cas Server默认已经实现好的基于JDBCAuthenticationHandler有三个,它们都继承自AbstractJdbcUsernamePasswordAuthenticationHandler,而且在认证过程中都需要一个DataSource。下面来对它们做一个简要的介绍。

 

1.1     BindModeSearchDatabaseAuthenticationHandler

       BindModeSearchDatabaseAuthenticationHandler将试图以传入的用户名和密码从配置的DataSource中建立一个连接,如果连接成功,则表示认证成功,否则就是认证失败。以下是BindModeSearchDatabaseAuthenticationHandler源码的一段主要代码,通过它我们可以明显的看清其逻辑:

    protected final boolean authenticateUsernamePasswordInternal(

        final UsernamePasswordCredentials credentials)

        throws AuthenticationException {

        final String username = credentials.getUsername();

        final String password = credentials.getPassword();

 

        try {

            final Connection c = this.getDataSource()

                .getConnection(username, password);

            DataSourceUtils.releaseConnection(c, this.getDataSource());

            returntrue;

        } catch (final SQLException e) {

            returnfalse;

        }

    }

 

       当然,这种实现也需要你的DataSource支持getConnection(user,password)才行,否则将返回falsedbcpBasicDataSource的不支持的,而c3p0ComboPooledDataSource支持。

       以下是一个使用BindModeSearchDatabaseAuthenticationHandler的配置示例:

   <bean id="authenticationManager"

      class="org.jasig.cas.authentication.AuthenticationManagerImpl">

      ...

      <property name="authenticationHandlers">

         <list>

            ...

            <bean class="org.jasig.cas.adaptors.jdbc.BindModeSearchDatabaseAuthenticationHandler">

                <property name="dataSource" ref="dataSource"/>

            </bean>

            ...

         </list>

      </property>

      ...

   </bean>

 

1.2     QueryDatabaseAuthenticationHandler

       使用QueryDatabaseAuthenticationHandler需要我们指定一个SQL,该SQL将接收一个用户名作为查询条件,然后返回对应的密码。该SQL将被QueryDatabaseAuthenticationHandler用来通过传入的用户名查询对应的密码,如果存在则将查询的密码与查询出来的密码进行匹配,匹配结果将作为认证结果。如果对应的用户名不存在也将返回false

       以下是QueryDatabaseAuthenticationHandler的一段主要代码:

    protected final boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {

        final String username = getPrincipalNameTransformer().transform(credentials.getUsername());

        final String password = credentials.getPassword();

        final String encryptedPassword = this.getPasswordEncoder().encode(

            password);

       

        try {

            final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);

            return dbPassword.equals(encryptedPassword);

        } catch (final IncorrectResultSizeDataAccessException e) {

            // this means the username was not found.

            returnfalse;

        }

    }

 

       上面的逻辑非常明显。此外,如你所见,QueryDatabaseAuthenticationHandler使用的用户名会经过PrincipalNameTransformer进行转换,而密码会经过PasswordEncoder进行编码。Cas Server中基于JDBCAuthenticationHandler实现中使用到的PrincipalNameTransformer默认是不进行任何转换的NoOpPrincipalNameTransformer,而默认使用的PasswordEncoder也是不会经过任何编码的PlainTextPasswordEncoder。当然了,cas-server-jdbc-support对它们也有另外两种支持,即PrefixSuffixPrincipalNameTransformerDefaultPasswordEncoder

1.2.1  PrefixSuffixPrincipalNameTransformer

       PrefixSuffixPrincipalNameTransformer的作用很明显,如其名称所描述的那样,其在转换时会将用户名加上指定的前缀和后缀。所以用户在使用的时候需要指定prefixsuffix两个属性,默认是空。

 

1.2.2  DefaultPasswordEncoder

       DefaultPasswordEncoder底层使用的是标准Java类库中的MessageDigest进行加密的,其支持MD5SHA等加密算法。在使用时需要通过构造参数encodingAlgorithm来指定使用的加密算法,可以使用characterEncoding属性注入来指定获取字节时使用的编码,不指定则使用默认编码。以下是DefaultPasswordEncoder的源码,其展示了DefaultPasswordEncoder的加密逻辑。

public final class DefaultPasswordEncoder implements PasswordEncoder {

 

    privatestaticfinalchar[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

 

    @NotNull

    privatefinal String encodingAlgorithm;

 

    private String characterEncoding;

 

    public DefaultPasswordEncoder(final String encodingAlgorithm) {

        this.encodingAlgorithm = encodingAlgorithm;

    }

 

    public String encode(final String password) {

        if (password == null) {

            returnnull;

        }

 

        try {

            MessageDigest messageDigest = MessageDigest

                .getInstance(this.encodingAlgorithm);

 

            if (StringUtils.hasText(this.characterEncoding)) {

                messageDigest.update(password.getBytes(this.characterEncoding));

            } else {

                messageDigest.update(password.getBytes());

            }

 

 

            finalbyte[] digest = messageDigest.digest();

 

            return getFormattedText(digest);

        } catch (final NoSuchAlgorithmException e) {

            thrownew SecurityException(e);

        } catch (final UnsupportedEncodingException e) {

            thrownew RuntimeException(e);

        }

    }

 

    /**

     * Takes the raw bytes from the digest and formats them correct.

     *

     * @param bytes the raw bytes from the digest.

     * @return the formatted bytes.

     */

    private String getFormattedText(byte[] bytes) {

        final StringBuilder buf = new StringBuilder(bytes.length * 2);

 

        for (int j = 0; j < bytes.length; j++) {

            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);

            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);

        }

        return buf.toString();

    }

 

    publicfinalvoid setCharacterEncoding(final String characterEncoding) {

        this.characterEncoding = characterEncoding;

    }

}

 

       如果在认证时需要使用DefaultPasswordEncoder,则需要确保数据库中保存的密码的加密方式和DefaultPasswordEncoder的加密算法及逻辑是一致的。如果这些都不能满足你的需求,则用户可以实现自己的PrincipalNameTransformerPasswordEncoder

 

       以下是一个配置使用QueryDatabaseAuthenticationHandler进行认证,且使用DefaultPasswordEncoder对密码进行MD5加密的示例:

   <bean id="authenticationManager"

      class="org.jasig.cas.authentication.AuthenticationManagerImpl">

      ...

      <property name="authenticationHandlers">

         <list>

            ...

            <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">

                <property name="dataSource" ref="dataSource"/>

                <property name="passwordEncoder" ref="passwordEncoder"/>

                <property name="sql" value="select password from t_user where username = ?"/>

            </bean>

            ...

         </list>

      </property>

      ...

   </bean>

 

   <bean id="passwordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">

      <constructor-arg value="MD5"/><!-- 加密算法 -->

   </bean>

 

1.3     SearchModeSearchDatabaseAuthenticationHandler

       SearchModeSearchDatabaseAuthenticationHandler的主要逻辑是将传入的用户名和密码作为条件从指定的表中进行查询,如果对应记录存在则表示认证通过。使用该AuthenticationHandler时需要我们指定查询时使用的表名(tableUsers)、用户名对应的字段名(fieldUser)和密码对应的字段名(fieldPassword)。此外,还可以选择性的使用PrincipalNameTransformerPasswordEncoder。以下是SearchModeSearchDatabaseAuthenticationHandler源码中的一段主要代码:

 

    private static final String SQL_PREFIX = "Select count('x') from ";

 

    @NotNull

    private String fieldUser;

 

    @NotNull

    private String fieldPassword;

 

    @NotNull

    private String tableUsers;

 

    private String sql;

 

    protectedfinalboolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {

        final String transformedUsername = getPrincipalNameTransformer().transform(credentials.getUsername());

        final String encyptedPassword = getPasswordEncoder().encode(credentials.getPassword());

 

        finalint count = getJdbcTemplate().queryForInt(this.sql,

           transformedUsername, encyptedPassword);

 

        return count > 0;

    }

 

    publicvoid afterPropertiesSet() throws Exception {

        this.sql = SQL_PREFIX + this.tableUsers + " Where " + this.fieldUser

        + " = ? And " + this.fieldPassword + " = ?";

    }

 

       以下是一个使用SearchModeSearchDatabaseAuthenticationHandler的配置示例:

 

   <bean id="authenticationManager"

      class="org.jasig.cas.authentication.AuthenticationManagerImpl">

      ...

      <property name="authenticationHandlers">

         <list>

            ...

            <bean class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler">

                <property name="dataSource" ref="dataSource"/>

                <property name="passwordEncoder" ref="passwordEncoder"/>

                <property name="tableUsers" value="t_user"/><!-- 指定从哪个用户表查询用户信息 -->

                <property name="fieldUser" value="username"/><!-- 指定用户名在用户表对应的字段名 -->

                <property name="fieldPassword" value="password"/><!-- 指定密码在用户表对应的字段名 -->

            </bean>

            ...

         </list>

      </property>

      ...

   </bean>

 

       至此,cas-server-support-jdbc中支持JDBC的三个AuthenticationHandler就讲完了。如果用户觉得它们都不能满足你的要求,则还可以选择使用自己实现的AuthenticationHandler。至于其它认证方式,请参考官方文档。

 

(注:本文是基于cas 3.5.2所写)

(注:原创文章,转载请注明出处。原文地址:http://elim.iteye.com/blog/2142616

 

目录
相关文章
|
7月前
|
关系型数据库 分布式数据库 数据库
成都晨云信息技术完成阿里云PolarDB数据库产品生态集成认证
近日,成都晨云信息技术有限责任公司(以下简称晨云信息)与阿里云PolarDB PostgreSQL版数据库产品展开产品集成认证。测试结果表明,晨云信息旗下晨云-站群管理系统(V1.0)与阿里云以下产品:开源云原生数据库PolarDB PostgreSQL版(V11),完全满足产品兼容认证要求,兼容性良好,系统运行稳定。
|
2月前
|
安全 Java 关系型数据库
springboot整合springsecurity,从数据库中认证
本文介绍了如何在SpringBoot应用中整合Spring Security,并从数据库中进行用户认证的完整步骤,包括依赖配置、数据库表创建、用户实体和仓库接口、用户详情服务类、安全配置类、控制器类以及数据库初始化器的实现。
186 3
springboot整合springsecurity,从数据库中认证
|
4月前
|
前端开发 数据库 数据库管理
阿里云数据库 ACP 问题之云厂商数据库认证相比单个数据库认证有什么优势
阿里云数据库 ACP 问题之云厂商数据库认证相比单个数据库认证有什么优势
|
7月前
|
NoSQL 安全 MongoDB
MongoDB为提供MongoDB数据库服务的云服务合作伙伴推出认证计划
Certified by MongoDB DBaaS计划还将为云计算合作伙伴提供构建深度技术集成所需的专业支持,同时还将携手MongoDB合作伙伴生态系统(MongoDB Partner Ecosystem)共同推出一系列联合的进入市场举措,使云服务合作伙伴能够助力其客户快速走向成功。
3157 0
|
7月前
|
存储 安全 Java
Spring Security实现基于数据库实现认证
本文档介绍了如何在Spring Security框架中基于数据库实现用户认证。首先,Spring Security提供了一个`UserDetailsService`接口,用于获取用户详细信息,通常在用户尝试登录时被调用。
103 5
|
7月前
|
Cloud Native 关系型数据库 分布式数据库
数据库性能诊断工具DBdoctor通过阿里云PolarDB产品生态集成认证
DBdoctor(V3.1.0)成功通过阿里云PolarDB分布式版(V2.3)集成认证,展现优秀兼容性和稳定性。此工具是聚好看科技的内核级数据库性能诊断产品,运用eBPF技术诊断SQL执行,提供智能巡检、根因分析和优化建议。最新版V3.1.1增加了对PolarDB-X和OceanBase的支持,以及基于cost的索引诊断功能。PolarDB-X是阿里巴巴的高性能云原生分布式数据库,兼容MySQL生态。用户可通过提供的下载地址、在线试用链接和部署指南体验DBdoctor。
405 0
|
7月前
|
存储 缓存 数据库
Shiro【核心功能、核心组件、项目搭建 、配置文件认证、数据库认证 】(一)-全面详解(学习总结---从入门到深化)
Shiro【核心功能、核心组件、项目搭建 、配置文件认证、数据库认证 】(一)-全面详解(学习总结---从入门到深化)
317 1
|
Kubernetes 关系型数据库 分布式数据库
kubeblocks完成阿里云PolarDB数据库产品生态集成认证
近日,杭州云猿生数据有限公司(以下简称云猿生)与阿里云PolarDB 开源数据库社区展开产品集成认证。测试结果表明,杭州云猿生数据有限公司旗下kubeblocks(V0.7.0)与阿里云以下产品:开源云原生数据库PolarDB 分布式版( V2.0 ),完全满足产品兼容认证要求,兼容性良好,系统运行稳定。
|
存储 Cloud Native 关系型数据库
星辰天合公司产品完成阿里云PolarDB数据库产品生态集成认证
近日,XSKY星辰天合旗下产品与阿里云PolarDB 开源数据库社区展开产品集成认证。测试结果表明,星辰天合旗下的融合计算管理平台XHERE(V2)、统一数据平台XEDP(V6)、天合翔宇分布式存储系统(V6)与阿里云的开源云原生数据库 PloarDB分布式版(V2.2)以及开源云原生数据库PolarDB PostgreSQL(V11),完全满足产品兼容认证要求,兼容性良好,系统运行稳定。
|
运维 安全 NoSQL
《阿里云认证的解析与实战-关系型数据库ACP认证》——数据库生态工具—— 二、数据管理DMS
《阿里云认证的解析与实战-关系型数据库ACP认证》——数据库生态工具—— 二、数据管理DMS
下一篇
DataWorks