大家好,欢迎来到IT知识分享网。
一、前言
任何一个管理信息系统都会有登录功能。我们简单可以通过用户名加密码加验证码进行登录。但是就是一个这样的简单功能却涉及的要求很多。
比如对账号的要求,对密码复杂度的要求,对登录时长的要求,对密码有效期的要求,对登录用户登录日志的记录,登录用户的权限等等。非常非常多。本文就介绍简单的登录功能。
二、登录功能数据库表设计
-- 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应用程序中,设计一个高效且安全的登录系统需要考虑以下几个关键需求:
- 用户注册与登录:允许用户注册账号并登录系统。
- 密码加密存储:使用安全的方法存储用户密码,如使用哈希加盐(Hashing with Salting)。
- 防止暴力激活成功教程:增加对连续登录失败的限制,以防止暴力激活成功教程攻击。
- 会话管理:为用户创建一个安全的会话,并在用户注销或会话过期后终止会话。
- 支持多用户类型:可能需要为不同用户类型(如管理员、普通用户)提供不同的权限级别。
- 验证码功能:为增强安全性,可以考虑使用验证码功能来防止机器人攻击。
- 记录与审计:记录所有登录活动,以便进行审计和监控。
- 国际化与本地化:支持多种语言,以满足不同地区用户的需求。
- 易用性与用户体验:设计简单、直观的界面和流程,方便用户快速完成登录操作。
- 支持社交登录:集成第三方认证服务,允许用户使用社交媒体账号登录。
- 安全性更新与通知:当系统有安全更新或风险时,能够及时通知用户。
二、开发实现
实现Java系统登录功能需要多个组件和技术的配合,以下是关键步骤和考虑因素:
- 设计数据库结构:为存储用户信息(如用户名、密码、邮箱等)设计数据库表结构。
- 选择认证方式:根据需求选择合适的认证方式,如基本身份验证、摘要认证等。
- 密码加密存储:使用如bcrypt、scrypt等算法对用户密码进行哈希加密存储,并加盐增加安全性。
- 实现注册与登录功能:创建注册和登录页面,处理表单提交,验证用户输入并与数据库进行交互。
- 处理会话管理:使用Java的会话管理机制(如HttpSession)来跟踪用户的登录状态和会话信息。
- 实现权限控制:根据用户类型或角色,使用Java的访问控制机制(如Java Security)来限制对特定资源的访问。
- 记录与审计日志:使用Java日志框架(如Log4j、SLF4J)记录所有登录活动,以便进行审计和监控。
- 集成验证码服务:如果需要验证码功能,可以考虑使用第三方验证码服务或自己实现。
- 支持多语言:使用Java的国际化和本地化API来支持多种语言环境。
- 集成第三方认证服务:使用OAuth、OpenID Connect等协议集成第三方认证服务,如Google、Facebook等。
- 前端与后端交互:使用Java的Web框架(如Spring MVC)处理前端请求并与后端服务进行交互。
- 测试与调试:对整个登录系统进行全面的测试,确保所有功能正常工作并修复潜在问题。
- 部署与监控:将应用程序部署到生产环境,并设置监控和告警以确保系统的稳定性与安全性。
三、安全考虑
设计Java系统登录功能时,安全性是最重要的考虑因素之一。以下是一些关键的安全建议和最佳实践:
- 使用HTTPS协议:确保应用程序之间的通信使用HTTPS协议进行加密,以防止数据泄露和中间人攻击。
- 防止SQL注入和跨站脚本攻击(XSS):对用户输入进行验证和清理,并使用预编译的SQL语句或ORM框架来防止SQL注入攻击;对输出进行适当的编码以防止XSS攻击。
- 防止跨站请求伪造(CSRF)攻击:在处理敏感操作时实施CSRF保护机制。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/125969.html