1. 程式人生 > >高校教師教研績效管理系統 大創專案中遇到的難點和BUG總結

高校教師教研績效管理系統 大創專案中遇到的難點和BUG總結

1.專案的POJO類一定要實現序列化介面,否則獲取到物件後無法使用其的get / set方法獲取和設定其屬性

        例子:在做登陸頁面時候,安全控制用的是彈簧安全,密碼加密演算法是BCrypt演算法由於之前重新搭建專案,忘記

將實體類實現序列化介面,從而導致後臺獲取到實體類物件例項後,無法使用getPassword來來來來方法獲取資料庫中的密碼,

導致前端傳送給後臺的資料無法與後臺資料進行正確比對,導致無法登入進入系統。 

       如何發現的:因為其在登入頁面進行密碼校驗時,導致系統一直進不去,因控制檯一直不報錯一直找不到錯

誤所在,遂嘗試不使用BCrypt演算法加密,使用固定使用者名稱登入,登入進入系統後,獲取使用者資料時候報了實體類未序列化

錯誤,遂找到了之前使用BCrypt演算法一直無法進入系統的原因

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
	xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
	<!--頁面攔截規則-->
	<http pattern="/login.html" security="none" ></http>
	<http pattern="/css/**" security="none"></http>
	<http pattern="/js/**" security="none"></http>
	<http pattern="/img/**" security="none"></http>
	<http pattern="/plugins/**" security="none"></http>
	<http use-expressions="false"> <!-- 是否實用spel表示式 -->
		<intercept-url pattern="/**" access="ROLE_TEACHER"/>
		<!-- 開啟表單的登入功能 -->
		<form-login login-page="/login.html" default-target-url="/admin/index.html" authentication-failure-url="/login.html" always-use-default-target="true"/>		<!-- 表單自動生成的頁面 -->
		<!-- 以下頁面不再攔截 -->
		<csrf disabled="true"/>
		<headers>
			<frame-options policy="SAMEORIGIN" />
		</headers>
		<logout/>
	</http>	
	<!-- 認證管理器 -->
	<!-- <authentication-manager>
		<authentication-provider> 
			<user-service>
				<user name="20181201" password="123456" authorities="ROLE_TEACHER"/>
				<user name="sunwukong" password="dasheng" authorities="ROLE_ADMIN"/>
			</user-service>
		</authentication-provider>
	</authentication-manager> -->
	<authentication-manager>
		<authentication-provider user-service-ref="userDetailsService"> 
			<password-encoder ref="bcryptEncoder"></password-encoder>
		</authentication-provider>
	</authentication-manager>
	<!-- 引用dubbo服務 -->
	<dubbo:application name="usrms-teacher-web" />
	<dubbo:registry address="zookeeper://192.168.25.128:2181"/>
	<!-- 用id標識後 可以被其他bean物件引用,name標識後不可被其他物件引用 -->
	<dubbo:reference  id="teacherService" interface="com.usrms.teacher.service.TeacherService" ></dubbo:reference>
	<!-- 相當於一個bean ,效果等同於註解支援 因為dubbox框架註解支援沒有寫此類所以bean的方式新增 -->
	<beans:bean id="userDetailsService" class="com.usrms.service.UserDetailsServiceImpl">
		<beans:property name="teacherService" ref="teacherService"></beans:property>
	</beans:bean>
	<beans:bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></beans:bean>
</beans:beans>	

2. BCrypt加密演算法通過密碼校驗實現修改密碼功能

例子:因為專案要做修改密碼的功能,所以需要知道BCrypt演算法。中如何校驗因為BCrypt演算法。用的是雜湊+鹽的方式,過程不可逆,無法對其進行解密但是通過對BCryptPasswordEncoder類的檢視發現其有自帶的密碼校驗方法

BCryptPasswordEncoder.matches()原始碼:

	public boolean matches(CharSequence rawPassword, String encodedPassword) {
		if (encodedPassword == null || encodedPassword.length() == 0) {
			logger.warn("Empty encoded password");
			return false;
		}

		if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
			logger.warn("Encoded password does not look like BCrypt");
			return false;
		}

		return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
	}

 通過觀察分析原始碼,則發現可以直接呼叫BCryptPasswordEncoder.matches()方法將從資料庫中獲取到的加密的密碼與前臺傳入的密碼進行校驗,方法會自動將前臺傳入的未加密密碼與資料庫中加密過的演算法進行比對,故解決了修改密碼的需求

專案中修改使用者密碼程式碼:

/**
	 * 修改使用者密碼
	 * @param oldPassword 原密碼
	 * @param newPassword 新密碼
	 * @return
	 */
	@RequestMapping("/alterPassword")
	public Result alterPassword(String oldPassword,String newPassword) {
		String username=SecurityContextHolder.getContext().getAuthentication().getName();
		TbTeacher teacher=teacherService.findOne(username);
		if(oldPassword==null||oldPassword.trim().length()==0) {
			return new Result(false,"原密碼輸入不能為空");
		}
		if(newPassword==null||newPassword.trim().length()==0) {
			return new Result(false,"新密碼輸入不能為空");
		}
		BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
		try {
			if(passwordEncoder.matches(oldPassword,teacher.getPassword())) {
				teacher.setPassword(passwordEncoder.encode(newPassword));
				teacherService.update(teacher);
				return new Result(true,"密碼修改成功,請重新登入");
			}else {
				return new Result(false,"原密碼輸入不正確");
			}
		}catch(Exception e) {
			e.printStackTrace();
			return new Result(false,"密碼修改失敗");
		}
	}