JRTLIS登录
之前一直没做登录一是登录涉及业务,框架还没完成的情况不想涉及业务。二是没想好怎么提供多产品适用的登录界面。
不同产品可能登录的组是不同的,如:医生的科室、护士的病区、检验的工作组、试剂的试剂组、血库的输血科。如果登录要把大家都融合进来势必增加登录的逻辑复杂度、同时绑死了各个业务快,这样不太合适,但是大家验证用户密码后都会选个角色,为此把验证成功后的选择称为角色(可以是检验的工作组、医生的科室、试剂的试剂组等),这样就能提供一个大家共用的登录界面。
首先抽取角色表
然后抽取角色菜单表
再抽取菜单功能点表
角色和菜单这些表大家共用,共用就可以共用登录和菜单逻辑代码。用户表以及用户和角色关联的表各种系统自由定义。
例如检验系统的用户角色定义
基于上面表设计提供登录接口供各个业务实现,登录的差异性由接口抽象出来,包含登录界面显示的标题、系统名称、角色名称、密码安全级别、密码长度、验证用户、返回角色密码、修改密码:
package JRT.Login;
import java.util.List;
import JRT.Login.SelectRoleDto;
/**
* 作为JRT实现登录的抽象接口,不同系统登录实现该接口,把接口实现类配置到容器里,通过给登录界面URL指定LoginType为配置对象ID实现不同系统的登录,
* 从而方便各个依赖JRT开发的系统共享登录和菜单功能部分,可以快速把登录和菜单并入自己系统而又不需要介入太多,自己可以用自己的用户表和用户权限部分。
*/
public interface ILogin {
/**
* 得到登录界面显示的大标题
*
* @return 大标题
*/
String GetSystemTitle();
/**
* 得到登录界面用户密码框上面显示的系统名称
*
* @return 系统名称
*/
String GetSystemName();
/**
* 得到登录界面Url显示的名称
*
* @return URL名称
*/
String GetUrlTitle();
/**
* 得到登录的角色类型名称,如:工作组、科室、试剂组等
*
* @return URL名称
*/
String GetRoleTypeName();
/**
* 返回空就是不要求密码强度,1,2,3密码要求加强
*
* @return
*/
String GetSYSPasswordLevel() throws Exception;
/**
* 返回要求的密码长度限制,有密码级别要求才限制强度
*
* @return
*/
int GetSYSPasswordLength() throws Exception;
/**
* 检查用户名和密码
*
* @param userCode 用户在登录界面输入的用户名
* @param pass 用户在登录界面输入的密码
* @return 是否验证通过
*/
boolean CheckUser(String userCode, String pass) throws Exception;
/**
* 检查用户名和密码
*
* @param userCode 用户在登录界面输入的用户名
* @return 是否验证通过
*/
List<SelectRoleDto> GetSelectRole(String userCode) throws Exception;
/**
* 修改用户密码,用户密码强度不符合时候修改密码调用的接口
*
* @param userCode 用户在登录界面输入的用户名
* @param passOld 用户在登录界面输入的老密码
* @param passNew 用户在登录界面输入的新密码
* @return 成功返回空,否则返回失败原因
*/
String ChangePassword(String userCode, String passOld, String passNew) throws Exception;
}
返回角色列表的实体类,登录时候借助此信息构造会话对象:
package JRT.Login;
/**
* 用户登录界面选择的角色数据实体
*/
public class SelectRoleDto {
/**
* 必须是JRTRole表的主键,用户选择角色后按此值加载菜单数据,会在登录时候放入会话对象
*/
public int RoleDR;
/**
* 登录界面选择角色下拉框显示的名称,会在登录时候放入会话对象
*/
public String RoleName;
/**
* 以^分割的会话信息串,给需要的地方直接使用,不同系统自己约定每位存什么,会在登录时候放入会话对象
*/
public String SessionStr;
/**
* 存用户主键,会在登录时候放入会话对象
*/
public String UserID;
/**
* 存用户代码,会在登录时候放入会话对象
*/
public String UserCode;
/**
* 存用户名称,会在登录时候放入会话对象
*/
public String UserName;
/**
* 用户登录的工作组或科室ID,会在登录时候放入会话对象
*/
public String GroupID;
}
检验的登录实现类:
package JRT.Login;
import JRT.Core.Dto.HashParam;
import JRT.Core.Util.LogUtils;
import JRT.Core.Util.PassWordUtil;
import JRT.DAL.ORM.EntityManager.EntityManagerFactory;
import JRT.DAL.ORM.EntityManager.IEntityManager;
import JRT.Login.SelectRoleDto;
import JRT.Model.Entity.*;
import java.util.ArrayList;
import java.util.List;
/**
* 作为登录到检验工作组的实现类,其他登录科室和试剂组的登录实现参照此类即可,由登录界面通过URL上的LoginType从容器获取登录实现类
*/
public class LoginLIS implements JRT.Login.ILogin {
/**
* 访问数据库
*/
private IEntityManager entityManager = null;
/**
* 给业务脚本提供的操作数据库的对象
*/
public IEntityManager EntityManager() {
if (entityManager == null) {
entityManager = EntityManagerFactory.CreateEntityManager("");
}
return entityManager;
}
/**
* 得到登录界面显示的大标题
*
* @return 大标题
*/
@Override
public String GetSystemTitle() {
return "检验信息管理系统";
}
/**
* 得到登录界面用户密码框上面显示的系统名称
*
* @return 系统名称
*/
@Override
public String GetSystemName() {
return "检验系统";
}
/**
* 得到登录界面Url显示的名称
*
* @return URL名称
*/
@Override
public String GetUrlTitle() {
return "JRTLIS © 1.0";
}
/**
* 得到登录的角色类型名称,如:工作组、科室、试剂组等
*
* @return URL名称
*/
@Override
public String GetRoleTypeName() {
return "工作组";
}
/**
* 返回空就是不要求密码强度,1,2,3密码要求加强
*
* @return
*/
@Override
public String GetSYSPasswordLevel() throws Exception {
//查询系统参数
SYSParameter dto = EntityManager().GetByColVal(SYSParameter.class, "Code", "SYSPasswordLevel");
if (dto != null) {
return dto.ParaValue;
}
return "";
}
/**
* 返回要求的密码长度限制,有密码级别要求才限制强度
*
* @return
*/
@Override
public int GetSYSPasswordLength() throws Exception {
//查询系统参数
SYSParameter dto = EntityManager().GetByColVal(SYSParameter.class, "Code", "SYSPasswordLength");
if (dto != null) {
if (dto.ParaValue != null && !dto.ParaValue.isEmpty()) {
return Integer.valueOf(dto.ParaValue);
}
}
return 9;
}
/**
* 检查用户名和密码
*
* @param userCode 用户在登录界面输入的用户名
* @param pass 用户在登录界面输入的密码
* @return 是否验证通过, 验证不通过的前端都统一返回用户名或密码错误
*/
@Override
public boolean CheckUser(String userCode, String pass) throws Exception {
//按代码查询用户
SYSUser user = EntityManager().GetByColVal(SYSParameter.class, "Code", userCode);
//没查到用户
if (user == null) {
LogUtils.WriteDebugLog("用户:" + userCode + "不存在");
return false;
}
//比较密码
boolean checkRes = PassWordUtil.PassCompare(pass, user.Password);
return checkRes;
}
/**
* 检查用户名和密码
*
* @param userCode 用户在登录界面输入的用户名
* @return 是否验证通过
*/
@Override
public List<SelectRoleDto> GetSelectRole(String userCode) throws Exception {
List<SelectRoleDto> retList = new ArrayList<>();
//按代码查询用户
SYSUser user = EntityManager().GetByColVal(SYSParameter.class, "Code", userCode);
//没查到用户
if (user == null) {
return retList;
}
HashParam para = new HashParam();
para.Add("UserDR", user.RowID);
List<SYSUserRole> roleList = EntityManager().FindAllSimple(SYSUserRole.class, para);
if (roleList != null && roleList.size() > 0) {
for (SYSUserRole dto : roleList) {
//取工作组数据
BTWorkGroup wgDto = EntityManager().DolerGet(BTWorkGroup.class, dto.WorkGroupDR);
//得到科室
BTDepartment depDto = EntityManager().DolerGet(BTDepartment.class, wgDto.DepartmentDR);
//得到医院
BTHospital hosDto = EntityManager().DolerGet(BTHospital.class, depDto.HospitalDR);
//岗位名称
String postName = "";
if (dto.PostDR != null) {
//取岗位数据
SYSPost postDto = EntityManager().DolerGet(BTWorkGroup.class, dto.WorkGroupDR);
postName = "[" + postDto.CName + "]";
}
SelectRoleDto role = new SelectRoleDto();
role.RoleDR = dto.RoleDR;
role.RoleName = wgDto.CName + postName;
//放工作组
role.GroupID = String.valueOf(dto.WorkGroupDR);
role.UserID = String.valueOf(user.RowID);
role.UserCode = user.Code;
role.UserName = user.CName;
role.SessionStr = user.RowID + "^" + dto.WorkGroupDR + "^" + depDto.RowID + "^" + dto.RoleDR + "^" + hosDto.RowID;
retList.add(role);
}
}
return retList;
}
/**
* 修改用户密码,用户密码强度不符合时候修改密码调用的接口
*
* @param userCode 用户在登录界面输入的用户名
* @param passOld 用户在登录界面输入的老密码
* @param passNew 用户在登录界面输入的新密码
* @return 成功返回空,否则返回失败原因
*/
@Override
public String ChangePassword(String userCode, String passOld, String passNew) throws Exception {
//按代码查询用户
SYSUser user = EntityManager().GetByColVal(SYSParameter.class, "Code", userCode);
//没查到用户
if (user == null) {
return "用户:" + userCode + "不存在!";
}
//比较密码
boolean checkRes = PassWordUtil.PassCompare(passOld, user.Password);
if (checkRes == false) {
return "用户名或密码不正确!";
}
//加密密码
user.Password = PassWordUtil.PassEntry(passNew);
//更新密码
List<String> upCol = new ArrayList<>();
upCol.add("Password");
int ret = EntityManager().Update(user, upCol);
if (ret == 1) {
return "";
} else {
return "修改密码发送错误!";
}
}
}
把检验的登录实现类配置到容器
登录后台通过容器取实现类为登录界面服务
import JRT.Core.Dto.HashParam;
import JRT.Core.MultiPlatform.JRTConfigurtaion;
import JRT.Core.MultiPlatform.JRTContext;
import JRT.DAL.ORM.EntityManager.EntityManagerImpl;
import JRT.Login.ILogin;
import JRTBLLBase.BaseHttpHandlerNoSession;
import JRTBLLBase.Helper;
import java.util.HashMap;
import java.util.List;
/**
* 作为登录界面的后台实现类,实现用户验证和修改密码登,为登录构造会话
*/
public class ashLogin extends BaseHttpHandlerNoSession {
/**
* 登录接口
*/
private ILogin login=null;
/**
* 得到登录的实现类
* @return
* @throws Exception
*/
private ILogin Login() throws Exception
{
//登录类型
String LoginType=Helper.ValidParam(JRT.Core.MultiPlatform.JRTContext.GetRequest(Request, "LoginType"), "LisLogin");
if(login==null) {
login = (ILogin) JRT.Core.Context.ObjectContainer.GetObject(LoginType);
}
return login;
}
/**
* 得到登录信息
* @return 常用信息的键值对
*/
public String GetLoginInfo() throws Exception
{
HashMap map=new HashMap();
//系统标题
map.put("SystemTitle",Login().GetSystemTitle());
//系统名称
map.put("SystemName",Login().GetSystemName());
//模块名称
map.put("UrlTitle",Login().GetUrlTitle());
//选择的角色名称
map.put("RoleTypeName",Login().GetRoleTypeName());
//密码级别
map.put("SYSPasswordLevel",Login().GetSYSPasswordLevel());
//密码长度
map.put("SYSPasswordLength",Login().GetSYSPasswordLength());
//显示的服务器IP
String ServiceShowIP= JRTConfigurtaion.Configuration("ServiceShowIP");
//密码长度
map.put("ServiceShowIP",ServiceShowIP);
//密码长度
map.put("ClientIP",JRTContext.GetClientIP(Request));
return Helper.Object2Json(map);
}
}
登录界面1.0,其他不同登录实现登录接口后配置到容器即可,给登录界面URL指定LoginType为配置的容器对象id即可
这样就可以极大的简化登录逻辑,让登录满足多种系统,这里依赖容器对登录实现进行解耦,把具体系统的登录业务和公共逻辑剥离,借助容器解耦是一种良好的编程模式,滥用容器就不是了。