基于ldap实现登录认证

        最近开发的应用需要外协人员实现登录认证,外协人员的密码等信息已经录入到ldap, 需要连接ldap进行登录认证。下面先介绍一下登录的网络旅程图。

一.nginx实现AES加密

nginx请求处理入口(前端请求为json格式)

 location /aes {default_type text/html;content_by_lua_block{local access_filter = require 'resty.aes_auth'local r = access_filter.aes_auth()ngx.header.content_type = "application/json; charset=UTF-8"if r == true then ngx.say([[{"code":200,"message":"Certification         successful!","data":true,"logCode":null}]])else ngx.say([[{"code":401,"message":"Authentication failed!","data":false,"logCode":null }]])endngx.exit(200)}}

 openresty请求认证接口脚本

local aes = require "resty.aes"
local cjson = require("cjson.safe")
local http = require("resty.http")
local key = "abcdefmJTNn}8Z#2`"
local iv = "1234567890123456"local _M = {}
function _M.aes_auth()ngx.req.read_body()local args,err = ngx.req.get_body_data()if (not args) or (err) thenreturn falseendlocal arg_json = cjson.decode(args)local username = arg_json.usernamelocal password = arg_json.passwordif (not username) or (not password) thenreturn falseendlocal cript = aes:new(key, nil, aes.cipher(128, "cbc"), {iv=iv, method=nil})local pwd = cript:encrypt(password)if pwd thenpwd = ngx.encode_base64(pwd)elsereturn falseendlocal httpc = http.new()local requestBody = {username = username,password = pwd}local json_body = cjson.encode(requestBody)local resp,err = httpc:request_uri("http://10.1.1.1:8080", {method = "POST",path = "/ldap/authUser",body = json_body,headers = {  ---header参数["Content-Type"] = "application/json;charset=UTF-8"}})if err thenreturn falseendlocal result = falseif resp thenlocal data = cjson.decode(resp.body).dataif data thenresult = dataendendreturn result
endreturn _M

 二.应用服务调用ldap服务

引入依赖

<!--ldap-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-ldap</artifactId><version>2.3.12.RELEASE</version>
</dependency>
<!--aes对称加密-->
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.56</version>
</dependency>

AES加密解密工具类,需要注意的是nginx不支持PKCS5Padding填充方式。

package com.xxx.xxx.xxx.util;import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Base64;import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import lombok.extern.slf4j.Slf4j;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.util.Base64Utils;/*** description:AES对称加密工具类** @author: lgq* @create: 2024-01-26 10:03*/
@Slf4j
public class AESUtil {/*** 日志相关*//*** 编码*/private static final String ENCODING = "UTF-8";/*** 算法定义*/private static final String AES_ALGORITHM = "AES";/*** 指定填充方式*/private static final String CIPHER_PADDING = "AES/ECB/PKCS5Padding";//必须使用PKCS7Padding,因为nginx不支持PKCS5Padding填充方式private static final String CIPHER_CBC_PADDING = "AES/CBC/PKCS7Padding";/*** 偏移量(CBC中使用,增强加密算法强度)*/private static final String IV_SEED = "1234567890123456";private static final String RANDOM_SECRET = "abcefmJTNn}8Z#2`";static {// 指定使用bouncycastle包来加密, 引入目的就是为了支持AES/CBC/PKCS7PaddingSecurity.addProvider(new BouncyCastleProvider());}public static String getRandomSecret() {return RANDOM_SECRET;}/*** AES加密** @param content 待加密内容* @param aesKey  密码* @return*/public static String encrypt(String content, String aesKey) {if (StringUtils.isBlank(content)) {log.info("AES encrypt: the content is null!");return null;}//判断秘钥是否为16位if (StringUtils.isNotBlank(aesKey) && aesKey.length() == 16) {try {//对密码进行编码byte[] bytes = aesKey.getBytes(ENCODING);//设置加密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance(CIPHER_PADDING);//选择加密cipher.init(Cipher.ENCRYPT_MODE, skeySpec);//根据待加密内容生成字节数组byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));//返回base64字符串return Base64Utils.encodeToString(encrypted);} catch (Exception e) {log.info("AES encrypt exception:" + e.getMessage());throw new RuntimeException(e);}} else {log.info("AES encrypt: the aesKey is null or error!");return null;}}/*** 解密** @param content 待解密内容* @param aesKey  密码* @return*/public static String decrypt(String content, String aesKey) {if (StringUtils.isBlank(content)) {log.info("AES decrypt: the content is null!");return null;}//判断秘钥是否为16位if (StringUtils.isNotBlank(aesKey) && aesKey.length() == 16) {try {//对密码进行编码byte[] bytes = aesKey.getBytes(ENCODING);//设置解密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance(CIPHER_PADDING);//选择解密cipher.init(Cipher.DECRYPT_MODE, skeySpec);//先进行Base64解码byte[] decodeBase64 = Base64Utils.decodeFromString(content);//根据待解密内容进行解密byte[] decrypted = cipher.doFinal(decodeBase64);//将字节数组转成字符串return new String(decrypted, ENCODING);} catch (Exception e) {log.info("AES decrypt exception:" + e.getMessage());throw new RuntimeException(e);}} else {log.info("AES decrypt: the aesKey is null or error!");return null;}}/*** AES_CBC加密** @param content 待加密内容* @param aesKey  密码* @return*/public static String encryptCBC(String content, String aesKey) {if (StringUtils.isBlank(content)) {log.info("AES_CBC encrypt: the content is null!");return null;}//判断秘钥是否为16位if (StringUtils.isNotBlank(aesKey) && aesKey.length() == 16) {try {//对密码进行编码byte[] bytes = aesKey.getBytes(ENCODING);//设置加密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);//偏移IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));//选择加密cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);//, iv//根据待加密内容生成字节数组byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));//返回base64字符串return Base64Utils.encodeToString(encrypted);} catch (Exception e) {log.info("AES_CBC encrypt exception:" + e.getMessage());throw new RuntimeException(e);}} else {log.info("AES_CBC encrypt: the aesKey is null or error!");return null;}}/*** AES_CBC解密** @param content 待解密内容* @param aesKey  密码* @return*/public static String decryptCBC(String content, String aesKey) {if (StringUtils.isBlank(content)) {log.info("AES_CBC decrypt: the content is null!");return null;}//判断秘钥是否为16位if (StringUtils.isNotBlank(aesKey) && aesKey.length() == 16) {try {//对密码进行编码byte[] bytes = aesKey.getBytes(ENCODING);//设置解密算法,生成秘钥SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);//偏移IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));// "算法/模式/补码方式"Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);//选择解密cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);//先进行Base64解码byte[] decodeBase64 = Base64Utils.decodeFromString(content);//根据待解密内容进行解密byte[] decrypted = cipher.doFinal(decodeBase64);//将字节数组转成字符串return new String(decrypted, ENCODING);} catch (Exception e) {log.info("AES_CBC decrypt exception:" + e.getMessage());throw new RuntimeException(e);}} else {log.info("AES_CBC decrypt: the aesKey is null or error!");return null;}}}

ladp配置类

package com.xxx.xxx.xxx.config;import javax.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;/*** description:LdapConfig** @author: lgq* @create: 2024-01-25 10:34*/
@Configuration
public class LdapConfig {@Resourceprivate LdapProperties ldapProperties;@Beanpublic LdapTemplate ldapTemplate() {LdapContextSource contextSource = new LdapContextSource();contextSource.setUrl(ldapProperties.getUrls());contextSource.setBase(ldapProperties.getBase());contextSource.setUserDn(ldapProperties.getUsername());contextSource.setPassword(ldapProperties.getPassword());contextSource.afterPropertiesSet();LdapTemplate ldapTemplate = new LdapTemplate(contextSource);ldapTemplate.setIgnorePartialResultException(true);ldapTemplate.setDefaultTimeLimit(1000);ldapTemplate.setDefaultCountLimit(100);return ldapTemplate;}}package com.xxx.xxx.xxx.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** description:ldapProperties** @author: lgq* @create: 2024-01-25 18:13*/
@Data
@ConfigurationProperties(prefix = "spring.ldap")
public class LdapProperties {/*** ldap服务地址*/private String urls;/*** 用户账号*/private String username;/*** 密码*/private String password;/*** base路径*/private String base;
}yml文件配置:spring:profiles: prodapplication:name: service-xxxldap:urls: "ldap://10.1.1.1:389"password: "xxxxxxxx"username: "cn=xxx.LDAP,ou=xxx,ou=xxx,dc=xxx,dc=xxx"base: "dc=xxx,dc=xxx"

认证服务类

package com.xxx.xxx.xxx.service.impl;import java.nio.charset.StandardCharsets;
import java.util.Base64;import javax.annotation.Resource;import com.xxx.xxx.xxx.service.LdapService;
import com.xxx.xxx.xxx.util.AESUtil;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.stereotype.Service;/*** description:LdapServiceImpl** @author: lgq* @create: 2024-01-26 09:26*/
@Service
@Slf4j
public class LdapServiceImpl implements LdapService {@Resourceprivate LdapTemplate ldapTemplate;/*** 验证登录用户的账号密码是否正确* @param username* @param password* @return*/@Overridepublic boolean authLoginUser(String username, String password) {if (ObjectUtils.isEmpty(username) || ObjectUtils.isEmpty(password)) {return false;}/*** aes对password进行解密*/String content = AESUtil.decryptCBC(password, AESUtil.getRandomSecret());if (ObjectUtils.isEmpty(content)) {return false;}String baseDn = "";String filter = "sAMAccountName=" + username;boolean result = false;try {result = ldapTemplate.authenticate(baseDn, filter, content);} catch (Exception ex) {log.error(ex.getMessage(), ex);} catch (Error er) {log.error(er.getMessage(), er);}return result;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/656828.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp多格式文件选择(APP,H5)

uniapp多格式文件选择&#xff08;APP&#xff0c;H5&#xff09; 背景实现代码实现运行结果注意事项 尾巴 背景 从手机选择文件进行上传是移动端很常见的需求&#xff0c;在原生开发时由于平台专一性很容易实现。但是用uniapp开发官方提供的API在APP平台只能选择图片和视频&a…

Java RC4加密算法

一、RC4加密算法 在密码学中&#xff0c;RC4&#xff08;来自Rivest Cipher 4的缩写&#xff09;是一种流加密算法&#xff0c;密钥长度可变。它加解密使用相同的密钥&#xff0c;因此也属于对称加密算法。 百度百科 - RC4&#xff1a;https://baike.baidu.com/item/RC4/34545…

乔拓云教育系统:打造培训机构全面数字化转型新篇章

在当今数字化、信息化高速发展的时代&#xff0c;教育培训机构也需要与时俱进&#xff0c;借助先进的管理工具提升运营效率&#xff0c;优化学员学习体验。乔拓云教育系统正是这样一个全面、高效、一站式的解决方案&#xff0c;为教育培训机构提供强大的技术支持和全方位的服务…

Focaler-IoU:更聚焦的IoU损失

摘要 边界框回归在目标检测领域中起着至关重要的作用&#xff0c;而目标检测的定位精度在很大程度上取决于边界框回归的损失函数。现有的研究通过利用边界框之间的几何关系来提高回归性能&#xff0c;而忽略了难易样本分布对边界框回归的影响。本文分析了难易样本分布对回归结…

零基础学编程初级视频教程,中文编程工具免费版下载及编程源码文件下载

零基础学编程初级视频教程&#xff0c;中文编程工具免费版下载及编程源码文件下载 编程初级视频教程链接 https://edu.csdn.net/course/detail/39061 编程工具及实例源码文件下载可以点击最下方官网卡片——软件下载——常用工具下载——编程工具免费版下载及实例源码下载。…

Ubuntu2204+ROS2(humble)+usb_cam内参标定

1、安装usb_cam包 pip install pydantic1.10.14sudo apt install ros-humble-usb-cam# 测试打开相机 ros2 launch usb_cam camera.launch.py# 显示图像 ros2 run image_view image_view image:/camera1/image_raw 2、安装 camera_calibration sudo apt install ros-humble-c…

PawSQL更新 | 新增18个SQL性能审核重写规则

PawSQL最新版本针对DML和DQL新增了审核和重写优化规则共计33个&#xff0c;整体的规则数目达到了83个&#xff0c;覆盖了正确性&#xff0c;安全性、可维护性、性能四个方面的SQL质量问题&#xff0c;并提供了优化建议&#xff0c;已经形成比较完善的针对数据操作的SQL质量审查…

防御保护--防火墙的可靠性

目录 前提&#xff1a; VGMP 接口故障切换场景 状态切换备份的过程 HRP 第一种备份方式 --- 自动备份 第二种备份方式 --- 手工备份 第三种备份方式 --- 快速备份 各备份场景过程分析 1&#xff0c;主备形成场景 2&#xff0c;主备模式下&#xff0c;接口故障切…

ElementUI组件:Button 按钮

button按钮 点击下载learnelementuispringboot项目源码 效果图 el-button.vue页面效果图 项目里el-button.vue代码 <script> export default {name: "el_button",// 注意这里的名称不能和 router inex.js里的name一样methods: {sendMsg() {// alert(1)xthi…

Linux系统中Docker的安装及常用组件的安装

什么是Docker Docker是一个开源的应用容器引擎&#xff0c;它可以让开发者将应用程序及其依赖项打包到一个可移植的镜像中&#xff0c;并发布到任何流行的操作系统上。Docker使用沙箱机制来隔离容器&#xff0c;使其相互独立&#xff0c;并简化了应用程序的部署和管理。沙箱机…

网工内推 | 资深网工,周末双休,厂商认证优先,14薪

01 群核科技 招聘岗位&#xff1a;资深网络运维工程师 职责描述&#xff1a; 1、负责公司IDC机房网络的规划及持续改进&#xff0c;保证网络稳定运行&#xff1b; 2、负责公司国内外传输线路建设&#xff0c;提高链路的高可用保证业务的SLA&#xff1b; 3、负责网络监控平台的…

阿尔泰科技—创新解决农业环境监测难题!

引言 “农业是人类生活中不可或缺的重要领域&#xff0c;而农业环境的监测与保护对于农作物的生长和农业生产的可持续发展至关重要。为了解决农业环境参数监测的难题&#xff0c;阿尔泰科技提供了一套先进的解决方案&#xff0c;利用USB5630-D数据采集卡搭配传感器测试方案&a…

Pi 5缺货?CM5什么出来?RP2024? 在 CES2024 上访谈树莓派CEO Eben Upton

Pi 5缺货&#xff1f;CM5什么出来&#xff1f;RP2024&#xff1f; 在 CES2024 上访谈树莓派CEO Eben Upton 树莓派 CEO Eben Upton 在 CES2024 上回答关于树莓派5缺货&#xff0c;Pi 5与AI&#xff0c;以及 CM5 和 RP2024 的未来发展这些相关问题。 00:00 - 树莓派上的AI &…

设计模式之框架源码剖析(实战+图解)

Java设计模式 1&#xff0c;概述 随着软件开发人员人数的增多&#xff0c;一些公司急需一些高端人才。作为一个高端人才&#xff0c;设计面向对象软件是必不可少的能力&#xff0c;而软件设计是需要很深的功力&#xff0c;设计模式就要求你必须掌握。 2&#xff0c;本章特色…

Linux(CentOS7)常见指令的常见用法(上)

指令功能hostname查看当前的主机名hostnamectl set-hostname修改主机名adduser添加用户passwd给用户设置密码userdel -r 删除用户ls显示某路径下的文件名ls -l ll 显示某路径下每个文件及其属性ls -la ls -al 显示某路径下所有文件包括隐藏文件及属性ls -d只看指定文件夹&…

5-1 A. DS串应用--KMP算法

题目描述 学习KMP算法&#xff0c;给出主串和模式串&#xff0c;求模式串在主串的位置 算法框架如下&#xff0c;仅供参考 输入 第一个输入t&#xff0c;表示有t个实例 第二行输入第1个实例的主串&#xff0c;第三行输入第1个实例的模式串 以此类推 输入样例&#xff1a; 3 qwe…

Mac下手动源码编译安装Swig

使用Homebrew安装 这个方式最简单&#xff0c;但是一般都是安装的最新版&#xff1a; brew install swig如果按照特定版本&#xff0c;需要看一个当前支持的列表&#xff1a; brew search swig brew install swig3源码编译安装 swig依赖pcre库&#xff0c;需要先安装pcre …

浅谈一下软件 QA 方法论 和 工具

浅谈一下软件 QA 方法论 和 工具 目录概述需求&#xff1a; 设计思路实现思路分析1.QA方法论2.Java QA工具 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result…

Linux系统——文本三剑客

目录 一、grep 1.格式 2.选项 2.1 grep重定向 2.2grep -m 匹配到几次停止 2.3grep -i 忽略大小写 2.4grep -n 显示行号 2.5grep -c 统计匹配行数 2.6grep -A 后几行 2.7grep -C 前后三行 2.8grep -B 前三行 2.9grep -e 或 2.10grep -w 匹配整个单词 2.11grep -r…

窥探向量乘矩阵的存内计算原理—基于向量乘矩阵的存内计算

在当今计算领域中&#xff0c;存内计算技术凭借其出色的向量乘矩阵操作效能引起了广泛关注。本文将深入研究基于向量乘矩阵的存内计算原理&#xff0c;并探讨几个引人注目的代表性工作&#xff0c;如DPE、ISAAC、PRIME等&#xff0c;它们在神经网络和图计算应用中表现出色&…