1. 程式人生 > >CAS自定義加密方式和自定義登入驗證

CAS自定義加密方式和自定義登入驗證

先搭建一個CAS服務:搭建教程

本專案中的自定義加和登入驗證中的加密方法使用了shiro,記得加shiro-all-XXX.jar。

原始碼下載

一、自定義加密

實現PasswordEncoder介面,public String encode(String password)返回加密後的密碼。

1、實現PasswordEncoder介面

package org.jasig.cas.web.pass;

import javax.validation.constraints.NotNull;

import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.jasig.cas.authentication.handler.PasswordEncoder;

/**
 * @author 74790
 * 2018年11月13日20:16:47
 * 自定義加密方式
 */
public class MyPassWord implements PasswordEncoder{
	
	@NotNull
	private Integer iterationCount;  //加密次數

	@Override
	public String encode(String password) {
		System.out.println("加密之前的密碼:"+password);
		String newpass = getNewPass(password, "salt", "MD5", 1024).toString();
		System.out.println("加密之後的密碼:"+newpass);
		return newpass;
	}
	
	//自定義加密方式,返回加密後的密碼字串
	private Object getNewPass(String password,String userName, String encryMode, Integer encryNum){
		Object salt = ByteSource.Util.bytes(userName);
		Object result = new SimpleHash(encryMode, password, salt, encryNum);
		return result;
	}

	public Integer getIterationCount() {
		return iterationCount;
	}

	public void setIterationCount(Integer iterationCount) {
		this.iterationCount = iterationCount;
	}
	
	
}

2、在deployerConfigContext.xml中配置自定義加密方式

    <!-- 自定義加密方式 -->
    <bean id="myPassWord" class="org.jasig.cas.web.pass.MyPassWord">  
	    <property name="iterationCount">
	        <value>1024</value>
	    </property>
	</bean>

3、將預設的認證方式按照下面要求修改,配置資料來源可以看本文章頭部的CAS服務搭建教程

將<property name="authenticationHandlers">標籤下面的

<beanclass="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />

換成:

<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
	<property name="dataSource" ref="dataSource"></property>
	<property name="sql" value="select userpassword from tuser where username=?"></property>
	<property name="passwordEncoder" ref="myPassWord"></property>
</bean> 

這裡已經實現了自定義的加密方式,但是這個PasswordEncoder接口裡面的public String encode(String password)方法不能傳入鹽值,如果沒有鹽值,兩個使用者一樣的密碼時,加密後的密碼就會一樣。所以此處需要鹽值加密。可以看下面的自定義登入驗證。

二、自定義登入驗證

1、繼承AbstractJdbcUsernamePasswordAuthenticationHandler類,重寫authenticateUsernamePasswordInternal方法。

package com.mfc.handler;

import javax.validation.constraints.NotNull;

import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.jasig.cas.adaptors.jdbc.AbstractJdbcUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.dao.IncorrectResultSizeDataAccessException;

/**
 * @author 74790
 * 自定義登入方式
 */
public class MyQueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {

	@NotNull
	private String sql;     //查詢sql
	@NotNull
	private String encryMode; //加密方式
	@NotNull 
	private Integer encryNum; //加密次數
	
	@Override
	protected boolean authenticateUsernamePasswordInternal(UsernamePasswordCredentials credentials)
			throws AuthenticationException {
		final String username = getPrincipalNameTransformer().transform(credentials.getUsername());
        final String password = credentials.getPassword();
        final String encryptedPassword = getPasswordEncoder1(password, username, this.encryMode, this.encryNum);
        
        try {
        	System.out.println("===頁面輸入密碼加密後:"+encryptedPassword);
            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.
            return false;
        }
	}
	
	
	//自定義加密方式,返回加密後的密碼字串
	private String getPasswordEncoder1(String password,String userName, String encryMode, Integer encryNum){
		Object salt = ByteSource.Util.bytes(userName);
		Object result = new SimpleHash(encryMode, password, salt, encryNum);
		return result.toString();
	}
	
	/**
     * @param sql The sql to set.
     */
    public void setSql(final String sql) {
        this.sql = sql;
    }
    
    public void setEncryMode(final String encryMode) {
    	this.encryMode = encryMode;
    }
    
    public void setEncryNum(final Integer encryNum){
    	this.encryNum = encryNum;
    }
}

2、在deployerConfigContext.xml修改配置

將<property name="authenticationHandlers">標籤下面的登入驗證方式修改一下,剛匯入CAS專案時的驗證方式是輸入使用者名稱和密碼同樣的字串就可以登入成功,即:

<beanclass="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />

修改成自定義的登入驗證方式:

<bean class="com.mfc.handler.MyQueryDatabaseAuthenticationHandler">
	<property name="dataSource" ref="dataSource"></property>
	<property name="sql" value="select userpassword from tuser where username=?"></property>
	<property name="encryMode" value="MD5"></property>
    <property name="encryNum" value="1024"></property>
</bean>

到此可以實現自定義登入驗證。