Java域登录实现
前言
因为公司最近需要项目登录域账号ad域服务器 本地账号,查了很多资料,都是零散的,所以这里整理一下步骤,希望对大家有所帮助
创建一个新的测试类
package com.numberone.web.controller.common;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.util.Hashtable;
/**
* Created by kelvan.cai on 2019/6/10 0010.
*/
public class AdLogin {
public static void main(String[] args) {
String userName = "123@qq.com";//AD域认证,用户的登录UserName
String password = "123";//AD域认证,用户的登录PassWord
String host = "*.*.*.*";//AD域IP,必须填写正确 *号改为自己的IP
String domain = "@qq.com";//域名后缀,例.@noker.cn.com 对应userName@
String port = "389"; //端口,一般默认389
String url = new String("ldap://" + host + ":" + port);//固定写法
String user = userName.indexOf(domain) > 0 ? userName : userName
+ domain;//网上有别的方法,但是在我这儿都不好使,建议这么使用
Hashtable env = new Hashtable();//实例化一个Env
DirContext ctx = null;
env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别(none,simple,strong),一种模式,这么写就行
env.put(Context.SECURITY_PRINCIPAL, user); //用户名
env.put(Context.SECURITY_CREDENTIALS, password);//密码
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");// LDAP工厂类
env.put(Context.PROVIDER_URL, url);//Url
try {
ctx = new InitialDirContext(env);// 初始化上下文
System.out.println("身份验证成功!");
} catch (AuthenticationException e) {
System.out.println("身份验证失败!");
e.printStackTrace();
} catch (javax.naming.CommunicationException e) {
System.out.println("AD域连接失败!");
e.printStackTrace();
} catch (Exception e) {
System.out.println("身份验证未知异常!");
e.printStackTrace();
} finally{
if(null!=ctx){
try {
ctx.close();
ctx=null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
AD域的userName和passWord认证成功后返回
Connected to the target VM, address: '127.0.0.1:62276', transport: 'socket'
Disconnected from the target VM, address: '127.0.0.1:62276', transport: 'socket'
身份验证成功!
Process finished with exit code 0
认证失败后返回
Connected to the target VM, address: '127.0.0.1:62380', transport: 'socket'
身份验证失败!
Disconnected from the target VM, address: '127.0.0.1:62380', transport: 'socket'
javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db1 ]
at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3154)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3100)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2886)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2800)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:319)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:216)
at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:101)
at com.numberone.web.controller.common.AdLogin.main(AdLogin.java:32)
Process finished with exit code 0
验证成功后,代入项目登录的位置,根据自己的登录界面和登录逻辑进行修改。这里我是 SysLoginService
######## 另外,域账号验证成功后,需要保存用户名才能进行正常的登录操作。否则,如果登录有验证用户的功能,会报找不到用户ad域服务器 本地账号,导致无法正常登录。正常见下文 替换域登录代码
/**
* 登录校验方法
*
* @author kelvan.cai
*/
@Component
public class SysLoginService
{
@Autowired
private ISysUserService userService;
/**
* 登录
*/
public SysUser login(String username, String password)
{
// 验证码校验
if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
}
String userName = username;//AD域认证,用户的登录UserName
String passWord = password;//AD域认证,用户的登录PassWord
String host = "*.*.*.*";//AD域IP,必须填写正确 *号改为自己的IP
String domain = "@qq.com";//域名后缀,例.@noker.cn.com 对应userName@
String port = "389"; //端口,一般默认389
String url = new String("ldap://" + host + ":" + port);//固定写法
String user2 = userName.indexOf(domain) > 0 ? userName : userName
+ domain;//网上有别的方法,但是在我这儿都不好使,建议这么使用
Hashtable env = new Hashtable();//实例化一个Env
DirContext ctx = null;
env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别(none,simple,strong),一种模式,这么写就行
env.put(Context.SECURITY_PRINCIPAL, user2); //用户名
env.put(Context.SECURITY_CREDENTIALS, passWord);//密码
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");// LDAP工厂类
env.put(Context.PROVIDER_URL, url);//Url
boolean flag=false;
try {
ctx = new InitialDirContext(env);// 初始化上下文
System.out.println("身份验证成功!");
flag=true;
} catch (AuthenticationException e) {
System.out.println("身份验证失败!");
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
e.printStackTrace();
} catch (javax.naming.CommunicationException e) {
System.out.println("AD域连接失败!");
e.printStackTrace();
} catch (Exception e) {
System.out.println("身份验证未知异常!");
e.printStackTrace();
} finally{
if(null!=ctx){
try {
ctx.close();
ctx=null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
if(flag){
//验证成功
System.out.println("域登录验证成功!");
//域登录验证成功之后获取用户名保存进数据库
SysUser userAD = new SysUser();
userAD.setLoginName(userName);
userAD.setUserName(userName);
if(userService.selectUserByLoginName(userName) == null){
userService.insertUser(userAD);
}else{
System.out.println("用户已存在!");
}
}else{
//验证失败
System.out.println("域登录验证失败!");
}
######你可以在这里运行代码,用AD域账号登录!
##欢迎大家加我QQ交流360056605