管理系统用户登录功能

一、前言

任何一个管理信息系统都会有登录功能。我们简单可以通过用户名加密码加验证码进行登录。但是就是一个这样的简单功能却涉及的要求很多。

比如对账号的要求,对密码复杂度的要求,对登录时长的要求,对密码有效期的要求,对登录用户登录日志的记录,登录用户的权限等等。非常非常多。本文就介绍简单的登录功能。

二、登录功能数据库表设计


-- Drop table

-- DROP TABLE public.t_user;

CREATE TABLE public.t_user (
	id varchar(32) NOT NULL,
	user_name varchar(255) NOT NULL,
	login_name varchar(255) NOT NULL,
	"password" varchar(255) NOT NULL,
	create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
	last_login_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
	deleted int4 NOT NULL DEFAULT 0,
	pwd_val_time timestamp NOT NULL,
	belong_code varchar(8) NULL,
	belong_name varchar(255) NULL,
	data_type varchar(255) NULL,
	phone varchar(255) NULL,
	CONSTRAINT t_user_pkey PRIMARY KEY (id)
);

 三、注册用户

注册用户分以下几步

1、判断新增的用户是否存在,如果存在不允许注册同账号的用户

2、判断用户名和密码是否是空

3、校验密码复杂度是否复合要求

4、对密码进行加密处理

5、报错新注册管理员账号

/**
	 * 保存后台管理用户信息
	 * @param tUser
	 * @return
	 */
	@ApiOperation(value = "保存后台管理用户信息", notes = "保存后台管理用户信息")
	@PostMapping("save")
	public ResponseData<Boolean> save(@RequestBody TUser tUser) {
		//先校验用户是否存在
		if(tUserService.userIsExists(tUser)) {
			log.error(TUserConstant.SAVE_USER_EXISTS);
			return ResponseData.error(TUserConstant.SAVE_USER_EXISTS);
		}

		if(StringUtils.isEmpty(tUser.getPassword()) || StringUtils.isEmpty(tUser.getLoginName())) {
			log.error(TUserConstant.SAVE_USER_EMP);
			return ResponseData.error(TUserConstant.SAVE_USER_EMP);
		}

		//校验密码复杂度
		Boolean checkPWD = tUserService.checkPWD(tUser.getPassword());
		if (!checkPWD) {
			log.error(TUserConstant.PWD_CHECK_ERROR);
			return ResponseData.error(TUserConstant.PWD_CHECK_ERROR);
		}
		
		tUser.setPassword(Des3Utils.get3DESEncryptECB(tUser.getPassword(), AES_KEY));
		tUser.setPwdValTime(new Date());
		boolean res = tUserService.save(tUser);
		if(res) {
			return ResponseData.success(true);
		}else {
			log.error(TUserConstant.SAVE_USER_ERROR);
			return ResponseData.error(TUserConstant.SAVE_USER_ERROR);
		}
	}

密码复杂度函数:

/**
	 * 校验复杂度
	 */
	public Boolean checkPWD(String PWD) {

		// 规定的正则表达式
		// (?![a-zA-Z]+$) 表示 字符串不能完全由大小写字母组成
		// (?![A-Z0-9]+$) 表示 字符串不能完全由大写字母和数字组成
		// (?![A-Z\W_]+$) 表示 字符串不能完全由大写字母和特殊字符组成
		// (?![a-z0-9]+$) 表示 字符串不能完全由小写字母和数字组成
		// (?![a-z\W_]+$) 表示 字符串不能完全由小写字母和特殊字符组成
		// (?![0-9\W_]+$) 表示 字符串不能完全由数字和特殊字符组成
		// [a-zA-Z0-9\W_]{8,} 表示 字符串应该匹配大小写字母、数字和特殊字符,至少匹配8次
		String regex = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![a-z0-9]+$)(?![A-Z\\W_]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,}$";

		return ReUtil.isMatch(regex, PWD);
	}

四、用户登录

1、限制频繁刷登录操作

2、校验码校验

3、校验用户和密码是否正确

4、判断密码是否过期是否需要重置密码

5、将登录信息写到缓存,设置不操作2小时过期

6、获取登录用户的权限

代码示例:

/**
	 * 后台管理用户登录
	 * @param tUser
	 * @return
	 */
	@ApiOperation(value = "后台管理用户登录", notes = "后台管理用户登录")
	@PostMapping("login")
	public ResponseData<String> login(@RequestBody Map<String,Object> map,HttpServletRequest request,HttpServletResponse response) {
		//防刷登录限制,一分钟内刷连续30次,限制访问
		if (!tUserService.isLimit(request,30)) {
			ResponseData<Object> responseData = ResponseData.error(ResponseCode.IS_LIMIT_ACC.getCode(),
					ResponseCode.IS_LIMIT_ACC.getMessage());
			tUserService.resNoPermiss(response, responseData);
			return ResponseData.error(TUserConstant.IS_LIMIT_ACC);
		}
		
		String verCode = "";
	  
		if(map.containsKey("verCode")) {
			verCode = map.get("verCode").toString();
		}else {
			return ResponseData.error(TUserConstant.VERCODE_EMP);
		} 
		
		 log.info("前端传入验证码:"+verCode);
		/**登录验证码(暂时屏蔽)**/
		if (!CaptchaUtil.ver(verCode, request)) {
			 log.info("验证码验证失败");
	         return ResponseData.error(TUserConstant.VERCODE_ERROE);
	     }
		
		TUser tUser = new TUser();
		if(map.containsKey("loginName")) {
			tUser.setLoginName(map.get("loginName").toString());
		} 
		if(map.containsKey("password")) {
			tUser.setPassword(map.get("password").toString()); 
		} 
		
		String pwdError = redisUtils.get(RedisKeys.getLoginPwdError(tUser.getLoginName()));
		if(!StringUtils.isEmpty(pwdError)) {
			if(Integer.parseInt(pwdError) > 4) {
				return ResponseData.error(TUserConstant.LOGIN_PERMISS_ERROR);	
			}
		}
		
		log.info("获取到后台登录的密码为:"+ tUser.getPassword());
		log.info("获取到后台登录的加密后的密码为:"+ Des3Utils.get3DESEncryptECB(tUser.getPassword(),AES_KEY));
		tUser.setPassword(Des3Utils.get3DESEncryptECB(tUser.getPassword(),AES_KEY));
		TUser tUserRes = tUserService.getByLoginName(tUser);
		if(null != tUserRes) {
			//判断密码更新时间是否超过有效期
			if (((new Date().getTime() - tUserRes.getPwdValTime().getTime())/(1000*3600*24)) > pwdValTime) {
				return ResponseData.error(-1,TUserConstant.PWD_VAL_TIME_ERROR);
			}
			//更新最后登录时间
			tUserService.updateUserLastLoginTime(tUser.getLoginName(), DateTimeUtils.getDateStr());
 
			// 添加session
			HttpSession session = request.getSession();
			try {
				session.setAttribute(Constant.CTG_ADMIN_USER_NAME,AesUtil.aesEncrypt(tUserRes.getUserName(),AES_KEY));
				session.setAttribute(Constant.CTG_ADMIN_USER_ID,AesUtil.aesEncrypt(tUserRes.getLoginName(),AES_KEY));
			} catch (Exception e) {
				e.printStackTrace();
			}
			//两个小时的有效期
			session.setMaxInactiveInterval(7200);
			
			//获取最新权限缓存
			tMenuService.getMenuUrlByloginName(tUserRes.getLoginName());
			
			return	ResponseData.success(tUserRes.getUserName());
		}else {
			
			log.error(TUserConstant.LOGIN_PSW_ERROR);
			return ResponseData.error(TUserConstant.LOGIN_PSW_ERROR);
		}
	}

五、单点登录

作为登录功能因为所有的系统都需要登录,往往我们就可以把登录功能封装处理供所有的系统使用。我们可以把它作为一个登录系统或者认证中心,也可以作为单点登录。

单点登录的原理:

 关于单点登录,我会上传一份源码到资源。开箱即用。

Java系统登录功能设计

一、需求分析

系统登录功能是任何应用程序的重要组成部分,它为用户提供了一个安全的方式来验证其身份并保护系统资源。在Java应用程序中,设计一个高效且安全的登录系统需要考虑以下几个关键需求:

  1. 用户注册与登录:允许用户注册账号并登录系统。
  2. 密码加密存储:使用安全的方法存储用户密码,如使用哈希加盐(Hashing with Salting)。
  3. 防止暴力破解:增加对连续登录失败的限制,以防止暴力破解攻击。
  4. 会话管理:为用户创建一个安全的会话,并在用户注销或会话过期后终止会话。
  5. 支持多用户类型:可能需要为不同用户类型(如管理员、普通用户)提供不同的权限级别。
  6. 验证码功能:为增强安全性,可以考虑使用验证码功能来防止机器人攻击。
  7. 记录与审计:记录所有登录活动,以便进行审计和监控。
  8. 国际化与本地化:支持多种语言,以满足不同地区用户的需求。
  9. 易用性与用户体验:设计简单、直观的界面和流程,方便用户快速完成登录操作。
  10. 支持社交登录:集成第三方认证服务,允许用户使用社交媒体账号登录。
  11. 安全性更新与通知:当系统有安全更新或风险时,能够及时通知用户。

二、开发实现

实现Java系统登录功能需要多个组件和技术的配合,以下是关键步骤和考虑因素:

  1. 设计数据库结构:为存储用户信息(如用户名、密码、邮箱等)设计数据库表结构。
  2. 选择认证方式:根据需求选择合适的认证方式,如基本身份验证、摘要认证等。
  3. 密码加密存储:使用如bcrypt、scrypt等算法对用户密码进行哈希加密存储,并加盐增加安全性。
  4. 实现注册与登录功能:创建注册和登录页面,处理表单提交,验证用户输入并与数据库进行交互。
  5. 处理会话管理:使用Java的会话管理机制(如HttpSession)来跟踪用户的登录状态和会话信息。
  6. 实现权限控制:根据用户类型或角色,使用Java的访问控制机制(如Java Security)来限制对特定资源的访问。
  7. 记录与审计日志:使用Java日志框架(如Log4j、SLF4J)记录所有登录活动,以便进行审计和监控。
  8. 集成验证码服务:如果需要验证码功能,可以考虑使用第三方验证码服务或自己实现。
  9. 支持多语言:使用Java的国际化和本地化API来支持多种语言环境。
  10. 集成第三方认证服务:使用OAuth、OpenID Connect等协议集成第三方认证服务,如Google、Facebook等。
  11. 前端与后端交互:使用Java的Web框架(如Spring MVC)处理前端请求并与后端服务进行交互。
  12. 测试与调试:对整个登录系统进行全面的测试,确保所有功能正常工作并修复潜在问题。
  13. 部署与监控:将应用程序部署到生产环境,并设置监控和告警以确保系统的稳定性与安全性。

三、安全考虑

设计Java系统登录功能时,安全性是最重要的考虑因素之一。以下是一些关键的安全建议和最佳实践:

  1. 使用HTTPS协议:确保应用程序之间的通信使用HTTPS协议进行加密,以防止数据泄露和中间人攻击。
  2. 防止SQL注入和跨站脚本攻击(XSS):对用户输入进行验证和清理,并使用预编译的SQL语句或ORM框架来防止SQL注入攻击;对输出进行适当的编码以防止XSS攻击。
  3. 防止跨站请求伪造(CSRF)攻击:在处理敏感操作时实施CSRF保护机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋力向前123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值