cas 4.2.7 maven cas-overlay服务端 IDEA工具关于国产达梦数据库配置以及MD5加盐验证
2018-01-11 14:55
555 查看
配置cas服务端(pom.xml)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd "> <modelVersion>4.0.0</modelVersion> <groupId>org.jasig.cas</groupId> <artifactId>cas-overlay</artifactId> <packaging>war</packaging> <version>1.0</version> <build> <resources> <resource> <directory>etc</directory> </resource> </resources> <plugins> <plugin> <groupId>com.rimerosolutions.maven.plugins</groupId> <artifactId>wrapper-maven-plugin</artifactId> <version>0.0.4</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <warName>cas</warName> <overlays> <overlay> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-webapp</artifactId> <excludes> <exclude>WEB-INF/cas.properties</exclude> <exclude>WEB-INF/classes/log4j2.xml</exclude> </excludes> </overlay> </overlays> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>${maven-jetty-plugin.version}</version> <configuration> <jettyXml>${basedir}/etc/jetty/jetty.xml,${basedir}/etc/jetty/jetty-ssl.xml,${basedir}/etc/jetty/jetty-https.xml</jettyXml> <systemProperties> <systemProperty> <name>org.eclipse.jetty.annotations.maxWait</name> <value>240</value> </systemProperty> </systemProperties> <webApp> <contextPath>/cas</contextPath> <overrideDescriptor>${basedir}/etc/jetty/web.xml</overrideDescriptor> </webApp> <webAppConfig> <allowDuplicateFragmentNames>true</allowDuplicateFragmentNames> </webAppConfig> <jvmArgs>-Dlog4j.configurationFile=/etc/cas/log4j2.xml -Xdebug -Xrunjdwp:transport=dt_socket,address=5000,server=y,suspend=n</jvmArgs> </configuration> </plugin> </plugins> <finalName>cas</finalName> </build> <dependencies> <dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-webapp</artifactId> <version>${cas.version}</version> <type>war</type> <scope>runtime</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.jasig.cas/cas-server-support-jdbc --> <dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-support-jdbc</artifactId> <version>${cas.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.6</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.43</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.11</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.8.RELEASE</version> </dependency> <dependency> <groupId>org.jetbrains</groupId> <artifactId>annotations-java5</artifactId> <version>15.0</version> </dependency> </dependencies> <properties> <cas.version>4.2.7</cas.version> <maven-jetty-plugin.version>9.3.6.v20151106</maven-jetty-plugin.version> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <repositories> <repository> <id>sonatype-releases</id> <url>http://oss.sonatype.org/content/repositories/releases/</url> </repository> <repository> <id>sonatype-snapshots</id> <url>https://oss.sonatype.org/content/repositories/snapshots/</url> </repository> <repository> <id>shibboleth-releases</id> <url>https://build.shibboleth.net/nexus/content/repositories/releases</url> </repository> </repositories> </project>
配置deployerConfigContext.xml文件
deployerConfigContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:sec="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <util:map id="authenticationHandlersResolvers"> <entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver"/> <entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver"/> </util:map> <util:list id="authenticationMetadataPopulators"> <ref bean="successfulHandlerMetaDataPopulator"/> <ref bean="rememberMeAuthenticationMetaDataPopulator"/> </util:list> <bean id="attributeRepository" class="org.jasig.services.persondir.support.NamedStubPersonAttributeDao" p:backingMap-ref="attrRepoBackingMap"/> <!-- <alias name="acceptUsersAuthenticationHandler" alias="primaryAuthenticationHandler" /> --> <alias name="personDirectoryPrincipalResolver" alias="primaryPrincipalResolver"/> <!--begin 从数据库中的用户表中读取 --> <bean id="MD5PasswordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder" autowire="byName"> <constructor-arg value="MD5"/> </bean> <!--class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">--> <bean id="queryDatabaseAuthenticationHandler" name="primaryAuthenticationHandler" class="com.MryxQueryDatabaseAuthenticationHandler"> <property name="passwordEncoder" ref="MD5PasswordEncoder"/> </bean> <!-- 本地mysql测试驱动连接--> <!--p:driverClass="com.mysql.jdbc.Driver" p:jdbcUrl="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull" p:user="root" p:password="root" --> <!-- 达梦数据库驱动连接--> <!---p:driverClass="dm.jdbc.driver.DmDriver" p:jdbcUrl="jdbc:dm://localhost:5236/TEST" p:user="TEST" p:password="test" --> <alias name="dataSource" alias="queryDatabaseDataSource"/> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"><value>dm.jdbc.driver.DmDriver</value></property> <property name="url"><value>jdbc:dm://localhost:5236/TEST</value></property> <property name="username"><value>TEST</value></property> <property name="password"><value>test</value></property> </bean> <!--end 从数据库中的用户表中读取 --> <util:map id="attrRepoBackingMap"> <entry key="uid" value="uid"/> <entry key="eduPersonAffiliation" value="eduPersonAffiliation"/> <entry key="groupMembership" value="groupMembership"/> <entry> <key> <value>memberOf</value> </key> <list> <value>faculty</value> <value>staff</value> <value>org</value> </list> </entry> </util:map> <alias name="serviceThemeResolver" alias="themeResolver"/> <alias name="jsonServiceRegistryDao" alias="serviceRegistryDao"/> <alias name="defaultTicketRegistry" alias="ticketRegistry"/> <alias name="ticketGrantingTicketExpirationPolicy" alias="grantingTicketExpirationPolicy"/> <alias name="multiTimeUseOrTimeoutExpirationPolicy" alias="serviceTicketExpirationPolicy"/> <alias name="anyAuthenticationPolicy" alias="authenticationPolicy"/> <alias name="acceptAnyAuthenticationPolicyFactory" alias="authenticationPolicyFactory"/> <bean id="auditTrailManager" class="org.jasig.inspektr.audit.support.Slf4jLoggingAuditTrailManager" p:entrySeparator="${cas.audit.singleline.separator:|}" p:useSingleLine="${cas.audit.singleline:false}"/> <alias name="neverThrottle" alias="authenticationThrottle"/> <util:list id="monitorsList"> <ref bean="memoryMonitor"/> <ref bean="sessionMonitor"/> </util:list> <alias name="defaultPrincipalFactory" alias="principalFactory"/> <alias name="defaultAuthenticationTransactionManager" alias="authenticationTransactionManager"/> <alias name="defaultPrincipalElectionStrategy" alias="principalElectionStrategy"/> <alias name="tgcCipherExecutor" alias="defaultCookieCipherExecutor"/> </beans>上述xml中关于达梦数据库的连接配置可直接copy你的项目中,修改ip,数据库连接密码等
(使用org.springframework.jdbc.datasource.DriverManagerDataSource方式)
修改cas.properties
cas4.2系列很多配置都改在了cas.properties里面了,本例中需要修改该文件。
增加配置:
cas.jdbc.authn.query.sql=select user_pwd,user_pwd_salt from sys_user where user_accout=?
查询 md5加密的密码 和 盐 的集合
自定义登录验证(加密规则)
新增MD5验证Java类MD5Util.java具体实现
package com; import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.Date; /** * @version 1.0 * @类名: MD5.java * @描述: 自定义MD5算法 */ public class MD5Util { /* * 下面这些S11-S44实际上是一个4*4的矩阵数据,用于进行MD5加密运算 */ static final int S11 = 7; static final int S12 = 12; static final int S13 = 17; static final int S14 = 22; static final int S21 = 5; static final int S22 = 9; static final int S23 = 14; static final int S24 = 20; static final int S31 = 4; static final int S32 = 11; static final int S33 = 16; static final int S34 = 23; static final int S41 = 6; static final int S42 = 10; static final int S43 = 15; static final int S44 = 21; static final byte[] PADDING = {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; private long[] state = new long[4]; // MD5计算过程中用到的核心数据 private long[] count = new long[2]; // MD5计算过程中用到的核心数据 private byte[] buffer = new byte[64]; // MD5计算过程中用到的核心数据 public String digestHexStr; // 最新一次计算结果的16进制ASCII表示 private byte[] digest = new byte[16]; // digest, 是最新一次计算结果的2进制内部表示,表示128bit的MD5值 public static final String HASH_ALGORITHM = "SHA-1"; // 加密算法 public static final int HASH_INTERATIONS = 1024; // 进行Hash迭代的次数 private static final int SALT_SIZE = 8; // 盐的位数 /** * 根据传入的字符串获取MD5加密结果(无需加盐) * * @param inbuf 需要加密的字符串 * @return 加密后的结果 */ public String getMD5ofStr(String inbuf) { md5Init(); md5Update(inbuf.getBytes(), inbuf.length()); md5Final(); digestHexStr = ""; for (int i = 0; i < 16; i++) { digestHexStr += byteHEX(digest[i]); } return digestHexStr; } /** * 获取加密盐 * * @return 加密盐 */ public static String getSalt() { byte[] salt = Digests.generateSalt(SALT_SIZE); String saltString = Encodes.encodeHex(salt); return saltString; } /** * 根据密码和加密盐获取加密后的结果 * * @param pwd 密码 * @param sSalt 加密盐 * @return */ public static String getPwdBySalt(String pwd, String sSalt) { byte[] bSalt = Encodes.decodeHex(sSalt); byte[] hashPassword = Digests.sha1(pwd.getBytes(), bSalt, HASH_INTERATIONS); return Encodes.encodeHex(hashPassword); } /** * 获取加密盐的byte * * @return 加密盐的byte */ public static byte[] getSaltByte() { byte[] salt = Digests.generateSalt(SALT_SIZE); return salt; } /** * 构造函数 */ public MD5Util() { md5Init(); return; } /** * 初始化函数,初始化核心变量 */ private void md5Init() { count[0] = 0L; count[1] = 0L; state[0] = 0x67452301L; state[1] = 0xefcdab89L; state[2] = 0x98badcfeL; state[3] = 0x10325476L; return; } /** * MD5位运算函数 * * @param x * @param y * @param z * @return */ private long F(long x, long y, long z) { return (x & y) | ((~x) & z); } /** * MD5位运算函数 * * @param x * @param y * @param z * @return */ private long G(long x, long y, long z) { return (x & z) | (y & (~z)); } /** * MD5位运算函数 * * @param x * @param y * @param z * @return */ private long H(long x, long y, long z) { return x ^ y ^ z; } /** * MD5位运算函数 * * @param x * @param y * @param z * @return */ private long I(long x, long y, long z) { return y ^ (x | (~z)); } /** * 对原位运算函数进行进一步的运算转换 * * @param a * @param b * @param c * @param d * @param x * @param s * @param ac * @return */ private long FF(long a, long b, long c, long d, long x, long s, long ac) { a += F(b, c, d) + x + ac; a = ((int) a << s) | ((int) a >>> (32 - s)); a += b; return a; } /** * 对原位运算函数进行进一步的运算转换 * * @param a * @param b * @param c * @param d * @param x * @param s * @param ac * @return */ private long GG(long a, long b, long c, long d, long x, long s, long ac) { a += G(b, c, d) + x + ac; a = ((int) a << s) | ((int) a >>> (32 - s)); a += b; return a; } /** * 对原位运算函数进行进一步的运算转换 * * @param a * @param b * @param c * @param d * @param x * @param s * @param ac * @return */ private long HH(long a, long b, long c, long d, long x, long s, long ac) { a += H(b, c, d) + x + ac; a = ((int) a << s) | ((int) a >>> (32 - s)); a += b; return a; } /** * 对原位运算函数进行进一步的运算转换 * * @param a * @param b * @param c * @param d * @param x * @param s * @param ac * @return */ private long II(long a, long b, long c, long d, long x, long s, long ac) { a += I(b, c, d) + x + ac; a = ((int) a << s) | ((int) a >>> (32 - s)); a += b; return a; } /** * 此方法是MD5的主计算过程,inbuf是要变换的字节串,inputlen是长度(由getMD5ofStr调用,调用前需要调用md5init方法) * * @param inbuf * @param inputLen */ private void md5Update(byte[] inbuf, int inputLen) { int i, index, partLen; byte[] block = new byte[64]; index = (int) (count[0] >>> 3) & 0x3F; if ((count[0] += (inputLen << 3)) < (inputLen << 3)) { count[1]++; } count[1] += (inputLen >>> 29); partLen = 64 - index; if (inputLen >= partLen) { md5Memcpy(buffer, inbuf, index, 0, partLen); md5Transform(buffer); for (i = partLen; i + 63 < inputLen; i += 64) { md5Memcpy(block, inbuf, 0, i, 64); md5Transform(block); } index = 0; } else { i = 0; } md5Memcpy(buffer, inbuf, index, i, inputLen - i); } /** * 整理和填写输出结果 */ private void md5Final() { byte[] bits = new byte[8]; int index, padLen; Encode(bits, count, 8); index = (int) (count[0] >>> 3) & 0x3f; padLen = (index < 56) ? (56 - index) : (120 - index); md5Update(PADDING, padLen); md5Update(bits, 8); Encode(digest, state, 16); } /** * byte数组的块拷贝函数,从input的inpos开始把len长度的字节拷贝到output的outpos位置开始 * * @param output * @param input * @param outpos * @param inpos * @param len */ private void md5Memcpy(byte[] output, byte[] input, int outpos, int inpos, int len) { int i; for (i = 0; i < len; i++) output[outpos + i] = input[inpos + i]; } /** * MD5核心变换程序(由md5Update调用) * * @param block 分块的原始字节 */ private void md5Transform(byte block[]) { long a = state[0], b = state[1], c = state[2], d = state[3]; long[] x = new long[16]; Decode(x, block, 64); /* Round 1 */ a = FF(a, b, c, d, x[0], S11, 0xd76aa478L); /* 1 */ d = FF(d, a, b, c, x[1], S12, 0xe8c7b756L); /* 2 */ c = FF(c, d, a, b, x[2], S13, 0x242070dbL); /* 3 */ b = FF(b, c, d, a, x[3], S14, 0xc1bdceeeL); /* 4 */ a = FF(a, b, c, d, x[4], S11, 0xf57c0fafL); /* 5 */ d = FF(d, a, b, c, x[5], S12, 0x4787c62aL); /* 6 */ c = FF(c, d, a, b, x[6], S13, 0xa8304613L); /* 7 */ b = FF(b, c, d, a, x[7], S14, 0xfd469501L); /* 8 */ a = FF(a, b, c, d, x[8], S11, 0x698098d8L); /* 9 */ d = FF(d, a, b, c, x[9], S12, 0x8b44f7afL); /* 10 */ c = FF(c, d, a, b, x[10], S13, 0xffff5bb1L); /* 11 */ b = FF(b, c, d, a, x[11], S14, 0x895cd7beL); /* 12 */ a = FF(a, b, c, d, x[12], S11, 0x6b901122L); /* 13 */ d = FF(d, a, b, c, x[13], S12, 0xfd987193L); /* 14 */ c = FF(c, d, a, b, x[14], S13, 0xa679438eL); /* 15 */ b = FF(b, c, d, a, x[15], S14, 0x49b40821L); /* 16 */ /* Round 2 */ a = GG(a, b, c, d, x[1], S21, 0xf61e2562L); /* 17 */ d = GG(d, a, b, c, x[6], S22, 0xc040b340L); /* 18 */ c = GG(c, d, a, b, x[11], S23, 0x265e5a51L); /* 19 */ b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aaL); /* 20 */ a = GG(a, b, c, d, x[5], S21, 0xd62f105dL); /* 21 */ d = GG(d, a, b, c, x[10], S22, 0x2441453L); /* 22 */ c = GG(c, d, a, b, x[15], S23, 0xd8a1e681L); /* 23 */ b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8L); /* 24 */ a = GG(a, b, c, d, x[9], S21, 0x21e1cde6L); /* 25 */ d = GG(d, a, b, c, x[14], S22, 0xc33707d6L); /* 26 */ c = GG(c, d, a, b, x[3], S23, 0xf4d50d87L); /* 27 */ b = GG(b, c, d, a, x[8], S24, 0x455a14edL); /* 28 */ a = GG(a, b, c, d, x[13], S21, 0xa9e3e905L); /* 29 */ d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8L); /* 30 */ c = GG(c, d, a, b, x[7], S23, 0x676f02d9L); /* 31 */ b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8aL); /* 32 */ /* Round 3 */ a = HH(a, b, c, d, x[5], S31, 0xfffa3942L); /* 33 */ d = HH(d, a, b, c, x[8], S32, 0x8771f681L); /* 34 */ c = HH(c, d, a, b, x[11], S33, 0x6d9d6122L); /* 35 */ b = HH(b, c, d, a, x[14], S34, 0xfde5380cL); /* 36 */ a = HH(a, b, c, d, x[1], S31, 0xa4beea44L); /* 37 */ d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9L); /* 38 */ c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60L); /* 39 */ b = HH(b, c, d, a, x[10], S34, 0xbebfbc70L); /* 40 */ a = HH(a, b, c, d, x[13], S31, 0x289b7ec6L); /* 41 */ d = HH(d, a, b, c, x[0], S32, 0xeaa127faL); /* 42 */ c = HH(c, d, a, b, x[3], S33, 0xd4ef3085L); /* 43 */ b = HH(b, c, d, a, x[6], S34, 0x4881d05L); /* 44 */ a = HH(a, b, c, d, x[9], S31, 0xd9d4d039L); /* 45 */ d = HH(d, a, b, c, x[12], S32, 0xe6db99e5L); /* 46 */ c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8L); /* 47 */ b = HH(b, c, d, a, x[2], S34, 0xc4ac5665L); /* 48 */ /* Round 4 */ a = II(a, b, c, d, x[0], S41, 0xf4292244L); /* 49 */ d = II(d, a, b, c, x[7], S42, 0x432aff97L); /* 50 */ c = II(c, d, a, b, x[14], S43, 0xab9423a7L); /* 51 */ b = II(b, c, d, a, x[5], S44, 0xfc93a039L); /* 52 */ a = II(a, b, c, d, x[12], S41, 0x655b59c3L); /* 53 */ d = II(d, a, b, c, x[3], S42, 0x8f0ccc92L); /* 54 */ c = II(c, d, a, b, x[10], S43, 0xffeff47dL); /* 55 */ b = II(b, c, d, a, x[1], S44, 0x85845dd1L); /* 56 */ a = II(a, b, c, d, x[8], S41, 0x6fa87e4fL); /* 57 */ d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0L); /* 58 */ c = II(c, d, a, b, x[6], S43, 0xa3014314L); /* 59 */ b = II(b, c, d, a, x[13], S44, 0x4e0811a1L); /* 60 */ a = II(a, b, c, d, x[4], S41, 0xf7537e82L); /* 61 */ d = II(d, a, b, c, x[11], S42, 0xbd3af235L); /* 62 */ c = II(c, d, a, b, x[2], S43, 0x2ad7d2bbL); /* 63 */ b = II(b, c, d, a, x[9], S44, 0xeb86d391L); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; } /** * 把long数组按顺序拆成byte数组,放到需要放的output中 * * @param output 需要存放的byte数组 * @param input 需要获取的数组 * @param len 存放的长度 */ private void Encode(byte[] output, long[] input, int len) { for (int i = 0, j = 0; j < len; i++, j += 4) { output[j] = (byte) (input[i] & 0xffL); output[j + 1] = (byte) ((input[i] >>> 8) & 0xffL); output[j + 2] = (byte) ((input[i] >>> 16) & 0xffL); output[j + 3] = (byte) ((input[i] >>> 24) & 0xffL); } } /** * Decode把byte数组按顺序合成成long数组,因为java的long类型是64bit的 * * @param output * @param input * @param len */ private void Decode(long[] output, byte[] input, int len) { for (int i = 0, j = 0; j < len; i++, j += 4) { output[i] = b2iu(input[j]) | (b2iu(input[j + 1]) << 8) | (b2iu(input[j + 2]) << 16) | (b2iu(input[j + 3]) << 24); } return; } /** * byte升位方法 * * @param b 需要升位的字节 * @return 升位后的ASCCI码 */ public static long b2iu(byte b) { return b < 0 ? b & 0x7F + 128 : b; } /** * 用来把一个byte类型的数据转换成字符串 * * @param ib 需要转换的字节 * @return 转换后的字符串 */ public static String byteHEX(byte ib) { char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; char[] arrChar = new char[2]; arrChar[0] = Digit[(ib >>> 4) & 0X0F]; arrChar[1] = Digit[ib & 0X0F]; return new String(arrChar); } /** * 用来把移动端传递密码之前,先把密码进行md5加密 * * @param pwd * @return */ public static String getMd5ForApp(String pwd) { // String[] ABC = {"a","b","c","d","e","f","g","h","i","g"}; String newSalt = ""; Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String nowDate = sdf.format(date); nowDate = nowDate.replace("-", ""); char[] dateArr = nowDate.toCharArray(); for (int i = 0; i < dateArr.length; i++) { newSalt += dateArr[i]; } byte[] bSalt = Encodes.decodeHex(newSalt); byte[] hashPassword = Digests.sha1(pwd.getBytes(), bSalt, HASH_INTERATIONS); return Encodes.encodeHex(hashPassword); } private static String byteArrayToHexString(byte b[]) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) { resultSb.append(byteToHexString(b[i])); } return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) { n += 256; } int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } public static String MD5Encode(String origin, String charsetname) { String resultString = null; try { resultString = new String(origin); MessageDigest md = MessageDigest.getInstance("MD5"); if (charsetname == null || "".equals(charsetname)) { resultString = byteArrayToHexString(md.digest(resultString.getBytes())); } else { resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); } } catch (Exception exception) { } return resultString; } private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; }
MryxQueryDatabaseAuthenticationHandler.java具体实现
package com; import org.apache.commons.lang3.StringUtils; import org.jasig.cas.adaptors.jdbc.AbstractJdbcUsernamePasswordAuthenticationHandler; import org.jasig.cas.authentication.HandlerResult; import org.jasig.cas.authentication.PreventedException; import org.jasig.cas.authentication.UsernamePasswordCredential; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.DataAccessException; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.stereotype.Component; import javax.security.auth.login.AccountNotFoundException; import javax.security.auth.login.FailedLoginException; import javax.sql.DataSource; import javax.sql.DataSource; import java.security.GeneralSecurityException; import java.util.Map; @Component("mryxQueryDatabaseAuthenticationHandler") public class MryxQueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler { @NotNull private String sql; @Override protected HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential) throws GeneralSecurityException, PreventedException { if (StringUtils.isBlank(this.sql) || getJdbcTemplate() == null) { throw new GeneralSecurityException("Authentication handler is not configured correctly"); } final String username = credential.getUsername(); //final String encryptedPassword = this.getPasswordEncoder().encode(credential.getPassword()); try { // final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username); final Map<String, Object> values = getJdbcTemplate().queryForMap(this.sql, username); String dbPassword = (String) values.get("user_pwd"); String salt = (String) values.get("user_pwd_salt"); //主要修改了这个地方,加入了自己的验证密码逻辑 if (!CheckPassword.validatePassword(credential.getPassword(), dbPassword,salt)) { throw new FailedLoginException("Password does not match value on record."); } } catch (final IncorrectResultSizeDataAccessException e) { if (e.getActualSize() == 0) { throw new AccountNotFoundException(username + " not found with SQL query"); } else { throw new FailedLoginException("Multiple records found for " + username); } } catch (final DataAccessException e) { throw new PreventedException("SQL exception while executing query for " + username, e); } return createHandlerResult(credential, this.principalFactory.createPrincipal(username), null); } /** * @param sql The sql to set. */ @Autowired public void setSql(@Value("${cas.jdbc.authn.query.sql:}") final String sql) { this.sql = sql; } @Override @Autowired(required = false) public void setDataSource(@Qualifier("queryDatabaseDataSource") final DataSource dataSource) { super.setDataSource(dataSource); } private static class CheckPassword { public static boolean validatePassword(String password, String dbPassword,String salt) { String pwd = MD5Util.getPwdBySalt(password, salt); if(dbPassword.equals(pwd)){ return true; }else{ return false; } } } }
修改deployerConfigContext.xml
queryDatabaseAuthenticationHandler的实现由org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler改为了com.mryx.cas.authentication.handler.MryxQueryDatabaseAuthenticationHandler
重启项目
中文本地化配置
修改WEB-INF\spring-configuration\applicationContext.xml
<util:list id="basenames"> <value>classpath:custom_messages</value> <value>classpath:messages_zh_CN</value> </util:list>
相关文章推荐
- sso 单点登录cas使用(2): cas 4.2.7 maven cas-overlay服务端数据库配置
- 单点登录之cas4.2.7服务端数据库配置(读数据库验证用户并对密码进行加密)
- 单点登录之cas4.2.7服务端数据库配置(读数据库验证用户并对密码进行加密)
- sso 单点登录cas使用(1): cas 4.2.7 maven cas-overlay部署服务端
- CAS 5.1.x 的搭建和使用(二)—— 通过Overlay搭建服务端-其它配置说明
- IntelliJ IDEA 工具使用 - 创建web项目以及tomcat配置
- idea集成开发工具的使用,tomcat服务器配置以及项目部署
- CAS 4.0.0RC 配置MD5验证功能
- CAS 5.1.x 的搭建和使用(二)—— 通过Overlay搭建服务端-其它配置说明
- 关于IDEA中项目pom.xml文件中jar报错,以及maven在IDEA中的配置!!!
- CAS 5.1.x 的搭建和使用(二)—— 通过Overlay搭建服务端-其它配置说明
- 关于CAS服务端登录前ajax访问后台方法被拦截的配置
- 关于CAS服务端登录前ajax访问后台方法被拦截的配置-另外一种实现方式
- 关于IDEA的基本环境配置以及快速使用(git拉载程序,Jdk安装,tomcat部署,应用程序打包运行)
- 3.服务端拦截器:验证是否发布成功,以及项目有感叹号问题
- Tomcat下载以及安装、eclipse工具配置tomcat9的具体步骤以及注意事项!!!
- JBoss AS7中的新概念-Domain[master配置domain.xml和host.xml和自己的管理员账号以及用于slave连接验证的账号,slave只需要配置host.xml配置文件即可]
- [置顶] 关于Idea基于maven创建springMvc项目中配置文件自动扫描找不到base-package问题
- 关于cas-client单点登录客户端拦截请求和忽略/排除不需要拦截的请求URL的问题(不需要修改任何代码,只需要一个配置)
- 关于md5的加密和解密的一些好的文章以及软件下载地址