3.3.替換用戶

2023-07-03 17:03 更新
BDF2中允許用戶替換其中的用戶、部門及崗位信息,而且這種替換可以根據(jù)需要只替換其中的用戶信息或只替換其中的部門信息或只替換其中的崗位信息,或者全部替換掉。替換后的用戶、部門及崗位信息可以來自用戶定義的任何源,比如其它數(shù)據(jù)庫、LDAP、WebService或其它系統(tǒng)。接下來我們就來介紹如何替換系統(tǒng)中采用的用戶信息。
為了演示替換操作,我們新建了一張用戶表名為demo_user的表,它的結(jié)構(gòu)比較簡單,只有三個字段,結(jié)構(gòu)圖如下:
用戶表創(chuàng)建好之后,接下來我們就可以編寫代碼了,首先第一步,我們需要實(shí)現(xiàn)AbstractUser抽象類,定義我們自己的用戶實(shí)體對象,其代碼如下:
DemoUser類源碼
import java.util.List;
import java.util.Map;
import com.bstek.bdf2.core.business.AbstractUser;
import com.bstek.bdf2.core.business.IDept;
import com.bstek.bdf2.core.business.IPosition;
import com.bstek.bdf2.core.model.Group;
import com.bstek.bdf2.core.model.Role;
public class DemoUser extends AbstractUser {
 private static final long serialVersionUID = 4348475318698431153L;
 private String username;
 private String cname;
 private String password;
 private List<IDept> depts;
 private List<IPosition> positions;
 private List<Role> roles;
 private List<Group> groups;
 public String getCname() {
 return cname;
 }
 public String getEname() {
 return cname;
 }
 /**
 * 當(dāng)前用戶是否為系統(tǒng)管理員,如果這個屬性返回true,那么就表示當(dāng)前用戶為系統(tǒng)管理員,
 * 所有權(quán)限對其都不起作用,反之則不然。
 * */
 public boolean isAdministrator() {
 return false;
 }
 /**
 * 當(dāng)前用戶的手機(jī)號
 * */
 public String getMobile() {
 return "13122112211";
 }
 /**
 * 當(dāng)前用戶的email地址
 * */
 public String getEmail() {
 return "test@sina.com";
 }
 /**
 * 當(dāng)前用戶所在部門
 * */
 public List<IDept> getDepts() {
 return depts;
 }
 /**
 * 當(dāng)前用戶所擁有的崗位
 * */
 public List<IPosition> getPositions() {
 return positions;
 }
 public void setPositions(List<IPosition> positions) {
 this.positions = positions;
 }
 public void setDepts(List<IDept> depts) {
 this.depts = depts;
 }
 /**
 * 當(dāng)前用戶所擁有的角色,權(quán)限需要使用
 * */
 public List<Role> getRoles() {
 return roles;
 }
 public void setRoles(List<Role> roles) {
 this.roles = roles;
 }
 /**
 * 當(dāng)前用戶所在群組
 * */
 public List<Group> getGroups() {
 return groups;
 }
 public void setGroups(List<Group> groups) {
 this.groups = groups;
 }
 /**
 * 用戶的其它元數(shù)據(jù)信息,如果我們的應(yīng)用用不到,可直接返回null
 * */
 public Map<String, Object> getMetadata() {
 return null;
 }
 public String getPassword() {
 return password;
 }
 public String getUsername() {
 return username;
 }
 /**
 * 判斷當(dāng)前用戶是否可用,可以在用戶來源信息中判斷這里取值,如果返回false,那么該用戶將不能登錄
 */
 public boolean isEnabled() {
 return true;
 }
 /**
 * 當(dāng)前用戶所在公司ID,如果當(dāng)前系統(tǒng)只給一家公司使用,這里返回一個固定值即可,
 * 如果是基于SAAS系統(tǒng),那么這里需要根據(jù)公司信息返回一個值
 * */
 public String getCompanyId() {
 return "bstek";
 }
 public void setUsername(String username) {
 this.username = username;
 }
 public void setCname(String cname) {
 this.cname = cname;
 }
 public void setPassword(String password) {
 this.password = password;
 }
}
在上面的代碼當(dāng)中,對于AbstractUser當(dāng)中的一些重要方法我們做了描述,AbstractUser當(dāng)中需要我們實(shí)現(xiàn)的方法都是必須的,而且都不能返回null(getMetadata方法除外),否則系統(tǒng)運(yùn)行時可能會產(chǎn)生空指針的異常,開發(fā)當(dāng)中,我們已盡量將AbstractUser類中需要實(shí)現(xiàn)的方法減到最少。

編寫好我們自定義的用戶實(shí)體對象后,接下來我們需要實(shí)現(xiàn)IUserService接口,在這個接口當(dāng)中定義了如何獲取用戶信息等相關(guān)操作,這個接口的源碼如下:
IUserService接口源碼
package com.bstek.bdf2.core.service;
import java.util.Collection;
import org.springframework.security.core.userdetails.UserDetailsService;
import com.bstek.bdf2.core.business.IUser;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;
/**
 * @since 2013-1-18
 * @author Jacky.gao
 */
public interface IUserService extends UserDetailsService {
 public static final String BEAN_ID="bdf2.userService";
 /**
 * 分頁加載用戶數(shù)據(jù)
 * @param page
Dorado7分頁對象,其中包含pageNo,pageSize,分頁后的數(shù)據(jù)也填充到這個page對象當(dāng)中,該參數(shù)不可為空
 * @param companyId 要加載哪個companyId下的用戶信息,該參數(shù)不可為空
 * @param criteria Dorado7條件對象,可從中取到相應(yīng)的條件值,該參數(shù)可為空
 */
 void loadPageUsers(Page<IUser> page,String companyId,Criteria criteria);
 /**
 * 加載指定部門ID下的用戶信息
 * @param deptId 隸屬的部門ID,該參數(shù)不可為空
 * @return 返回取到的用戶集合
 */
 Collection<IUser> loadUsersByDeptId(String deptId);
 /**
 * 檢查用戶密碼是否正確,如果不正確返回錯誤消息,如正確則返回null
 * @param username 用戶名
 * @param password 要檢查未加密的密碼
 * @return 不正確返回錯誤消息,如正確則返回null
 */
 String checkPassword(String username,String password);
 /**
 * 修改指定用戶的密碼信息
 * @param username 用戶名
 * @param newPassword 新密碼
 */
 void changePassword(String username,String newPassword);
 /**
 * 注冊一個系統(tǒng)管理員賬號
 * @param username 用于登錄的用戶名
 * @param cname 中文名
 * @param ename 英文名
 * @param password 密碼
 * @param mobile 手機(jī)號 
 * @param email 電子郵件
 * @param companyId 所在公司ID
 */
 void registerAdministrator(String username,String cname,String ename,String password,String
email,String mobile,String companyId);
 /**
 * 根據(jù)用戶名,實(shí)現(xiàn)化一個空的用戶對象供系統(tǒng)使用,實(shí)例化的用戶對象,只需要將給定的用戶名填充進(jìn)去即可
 * @param username 用戶名
 * @return 實(shí)例化后的用戶對象
*/
IUser newUserInstance(String username);
}
接口中每個方法都有詳細(xì)的解釋,我們需要看理解它,接下來,我們來編寫基于DemoUser的IUserService接口實(shí)現(xiàn)類,來從之前定義的demo_user表中獲取用戶信息,實(shí)現(xiàn)類代碼如下:
IUserService接口實(shí)現(xiàn)類示例
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.bstek.bdf2.core.business.IUser;
import com.bstek.bdf2.core.orm.jdbc.JdbcDao;
import com.bstek.bdf2.core.service.IUserService;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;
public class DemoUserService extends JdbcDao implements IUserService {
 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
 String sql="select username,password,cname from demo_user where username=?";
 List<IUser> users=this.getJdbcTemplate().query(sql, new Object[]{username}, new UserMapper());
 if(users.size()==0){
 throw new UsernameNotFoundException("User ["+username+"] is not exist!");
 }
 return users.get(0);
 }
 public void loadPageUsers(Page<IUser> page, String companyId,
 Criteria criteria) {
 String sql="select username,password,cname from demo_user where username=?";
 Collection<IUser> users=this.getJdbcTemplate().query(sql,new UserMapper());
 page.setEntities(users);
 }
 public Collection<IUser> loadUsersByDeptId(String deptId) {
 return Collections.EMPTY_LIST;
 }
 public String checkPassword(String username, String password) {
 return null;
 }
 public void changePassword(String username, String newPassword) {
 }
 public void registerAdministrator(String username, String cname,
 String ename, String password, String email, String mobile,
 String companyId) {
 }
 public IUser newUserInstance(String username) {
 DemoUser user=new DemoUser();
 user.setUsername(username);
 return user;
 }
 class UserMapper implements RowMapper<IUser>{
 public DemoUser mapRow(ResultSet rs, int rowNum) throws SQLException {
 DemoUser user=new DemoUser();
 user.setCname(rs.getString("cname"));
 user.setPassword(rs.getString("password"));
 user.setUsername(rs.getString("username"));
 return user;
 }
 }
}
在這個接口實(shí)現(xiàn)當(dāng)中,我們采用的是JdbcDao實(shí)現(xiàn)從demo_user表中獲取用戶信息,這其中我們保持checkPassword、changePassword與registerAdministrator三個方法為空,那么對應(yīng)頁面當(dāng)中用戶密碼修改及注冊系統(tǒng)管理員兩塊功能就不能正常使用,您可以去實(shí)現(xiàn)一把。

再次,我們還需要實(shí)現(xiàn)IFrameworkService接口,這個接口比較簡單,其中只有一個方法需要我們實(shí)現(xiàn),這個方法的作用是處理用戶登錄時用戶密碼驗(yàn)證的,我們的實(shí)現(xiàn)類代碼如下:
IFrameworkService實(shí)現(xiàn)類示例
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import com.bstek.bdf2.core.business.IUser;
import com.bstek.bdf2.core.service.IFrameworkService;
public class DemoFrameworkService implements IFrameworkService {
 public void authenticate(IUser user,
 UsernamePasswordAuthenticationToken authentication)
 throws AuthenticationException {
 DemoUser u=(DemoUser)user;
 String pwd=(String)authentication.getCredentials();
 if(!u.getPassword().equals(pwd)){
 throw new BadCredentialsException("The password is invalid");
 }
 }
}
可以看到,代碼比較簡單,就是判斷用戶密碼是否正確,如果不正確拋出一個BadCridentialsException即可。

上述三個接口實(shí)現(xiàn)完成之后,最后,我們需要將實(shí)現(xiàn)的DemoUserService及DemoFrameworkService配置到Spring當(dāng)中,以替換系統(tǒng)自帶的IUserService及IFrameworkService的默認(rèn)實(shí)現(xiàn)類,首先我們來看如何配置DemoUserService實(shí)現(xiàn)類。
打開位于WEB-INF/dorado-home目錄下的datasources.xml文件,在其中添加如下配置:
DemoUserService配置示例
<bean id="demoUserService" class="ext.DemoUserService"></bean>
 <bdf:user-service ref="demoUserService"/>
第一行,我們將DemoUserService配置成一個bean,其id為demoUserService ,第二行我們利用BDF2提供的namespacescheam將系統(tǒng)默認(rèn)的IUserService實(shí)現(xiàn)用demoUserService bean替換,當(dāng)然如果您沒有引入BDF2提供的namespacescheam,可以用下面的配置來代碼上面兩行配置信息:
DemoUserService另一種配置
<bean id="bdf2.userService" class="ext.DemoUserService"></bean>
可以看到,這種配置更新簡單,只需要一行就可以搞定,但前提是這個bean的ID必須是bdf2.userService。接下來我們看看如何配置DemoFrameworkService類,同樣的方法,在datasources.xml當(dāng)中添加下面兩行配置:
DemoFrameworkService配置
<bean id="demoFrameworkService" class="ext.DemoFrameworkService"></bean>
 <bdf:framework-service ref="demoFrameworkService"/>
同樣,如果您沒有引入BDF2提供的namespace scheam,可以用下面的一行替代上述配置:
DemoFrameworkService另一種配置
<bean id="bdf2.frameworkService" class="ext.DemoFrameworkService"></bean>
需要注意的是其ID必須為bdf2.frameworkService。

上述操作完成之后,就可以在demo_user中插入一個用戶,啟動我們應(yīng)用進(jìn)行登錄了。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號