- 浏览: 555280 次
- 性别:
- 来自: 长沙
文章分类
- 全部博客 (145)
- apache-struts (3)
- apache-shiro (4)
- apache-wicket (1)
- spring (34)
- spring-data-jpa (2)
- spring-mvc (20)
- spring-security (1)
- spring-webflow (1)
- hibernate (2)
- mongodb (1)
- ibatis (5)
- mysql (4)
- 开源组件 (18)
- java (3)
- maven (7)
- jBPM (1)
- EJB (1)
- JMS (2)
- servlet / jsp (9)
- javascript / jquery (10)
- 工作技巧 (12)
- ubuntu (6)
- bootstrap (10)
- javaee (1)
- 他山石 (7)
- jetbrick (1)
最新评论
-
yubao2008:
[size=x-small]为什么我也这样试了, 就是没有生效 ...
javax.servlet.http.HttpServletResponse 得到 status_code -
chenrl:
...
SpringMVC杂记(十五) spring-mvc controller 的切面 -
LONGTENGLONG:
你好,这样配置的,得到的集合为空,是什么原因?
apache-shiro杂记(一) 统计在线用户数目 -
xiafengfeiwu:
[flash=200,200][url]引用[/url][/f ...
apache-shiro 学习笔记 -
3108493554:
你好 ,有些问题想请教下,加下我qq310849354,你这上 ...
SpringMVC杂记(十二) 自定义Interceptor从Active Directory得到域信息
一)最近项目中要求实现Web应用的SSO(Single Sign On),即对于已经登录到Windows Domain中的用户,不需要输入用户名、密码而直接使用当前登录的Domain用户信息进行验证,如果验证成功则进入,否则拒绝进入。
参考了一下其他朋友的博客,大致了解了一下NTLM协议。
二) 我设计一个Interceptor,通过这个Interceptor的请求的session就会自然被设置上域名和用户名。
当然,不一定要用interceptor,servlet-filter一样可以实现同样的功能。spring-mvc用习惯了,还是interceptor顺手一些。
其中被注入的requestPredicate,是一个谓词,用来过滤一些请求,不满足的谓词要求的request会被忽略掉。如下面这个谓词用来判断Client是否已经在公司的域里了
三) 完成登录功能,登录还是由安全框架负责,如spring-security或apache-shiro
本文不赘述!
四) 开源软件jcifs的maven坐标
参考了一下其他朋友的博客,大致了解了一下NTLM协议。
二) 我设计一个Interceptor,通过这个Interceptor的请求的session就会自然被设置上域名和用户名。
<mvc:interceptor> <mvc:mapping path="/security/login"/> <bean class="ying.interceptor.ADUserInfoSetInterceptor"> <property name="domain" value="*.*.com" /> <property name="domainController" value="192.168.**" /> <!-- 域服务器ip --> <property name="requestPredicate"> <bean class="ying.function.InDomainPredicate" /> </property> </bean> </mvc:interceptor>
当然,不一定要用interceptor,servlet-filter一样可以实现同样的功能。spring-mvc用习惯了,还是interceptor顺手一些。
其中被注入的requestPredicate,是一个谓词,用来过滤一些请求,不满足的谓词要求的request会被忽略掉。如下面这个谓词用来判断Client是否已经在公司的域里了
package ying.function; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import javax.servlet.http.HttpServletRequest; import org.apache.commons.collections.Predicate; import org.apache.commons.lang.StringUtils; public class InDomainPredicate implements Predicate { @Override public boolean evaluate(Object object) { if (! (object instanceof HttpServletRequest)) { return false; } HttpServletRequest request = (HttpServletRequest) object; String ip = request.getRemoteHost(); if ("127.0.0.1".equals(ip) || "localhost".equals(ip)) { return false; } try { Process p = Runtime.getRuntime().exec(String.format("nbtstat -A %s", ip)); InputStreamReader ir = new InputStreamReader(p.getInputStream()); LineNumberReader input = new LineNumberReader(ir); String workstation = null; String domain = null; int k = 0; for (int i = 1; i < 20; i++) { String str = StringUtils.defaultIfEmpty((input.readLine()), ""); if (str.indexOf("<00>") != -1) { if (StringUtils.isEmpty(workstation)) { workstation = str.substring(0, str.indexOf("<00>")).trim(); k = i; } if (StringUtils.isEmpty(domain) && (k > 0 && (i == k + 1))) { domain = str.substring(0, str.indexOf("<00>")).trim(); } } } return (workstation.startsWith("ZT") && workstation.contains("-") && "ZTGAME".equals(domain)); } catch (IOException e) { return false; } } }
package ying.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import jcifs.Config; import jcifs.UniAddress; import jcifs.ntlmssp.Type1Message; import jcifs.ntlmssp.Type2Message; import jcifs.ntlmssp.Type3Message; import jcifs.smb.SmbSession; import jcifs.util.Base64; import org.apache.commons.collections.Predicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; public class ADUserInfoSetInterceptor extends HandlerInterceptorAdapter implements InitializingBean { private static final Logger LOGGER = LoggerFactory.getLogger(ADUserInfoSetInterceptor.class); private String domainController = null; private String domain = null; private String useExtendedSecurity = "false"; private String lmCompatibility = "0"; private String cachePolicy = "1200"; private String soTimeout = "1800000"; private Predicate requestPredicate; private String domainAttributeName = "domainAttributeName"; private String nameAttributeName = "nameAttributeName"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (requestPredicate != null && ! requestPredicate.evaluate(request)) { LOGGER.debug("requestPredicate.evaluate(request) == false"); return true; } UniAddress dc = null; String msg = request.getHeader("Authorization"); if (msg != null && msg.startsWith("NTLM ")) { byte[] src = Base64.decode(msg.substring(5)); dc = UniAddress.getByName(domainController, true); byte[] challenge = SmbSession.getChallenge(dc); if (src[8] == 1) { Type1Message type1 = new Type1Message(src); Type2Message type2 = new Type2Message(type1, challenge, null); msg = Base64.encode(type2.toByteArray()); if (response != null) { response.setHeader("WWW-Authenticate", "NTLM " + msg); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentLength(0); response.flushBuffer(); LOGGER.debug("C <-- S 401 Unauthorized WWW-Authenticate: NTLM <base64-encoded type-2-message>"); return false; } } else if (src[8] == 3) { Type3Message type3 = new Type3Message(src); byte[] lmResponse = type3.getLMResponse(); if (lmResponse == null) lmResponse = new byte[0]; byte[] ntResponse = type3.getNTResponse(); if (ntResponse == null) ntResponse = new byte[0]; request.getSession(true).setAttribute(this.nameAttributeName, type3.getUser()); request.getSession(true).setAttribute(this.domainAttributeName, type3.getDomain()); LOGGER.debug("C --> S GET ... Authorization: NTLM <base64-encoded type-3-message>"); } } else { response.setHeader("WWW-Authenticate", "NTLM"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentLength(0); response.flushBuffer(); LOGGER.debug("C <-- S 401 Unauthorized"); return false; } return true; } private void init() { Config.setProperty("jcifs.smb.client.soTimeout", getSoTimeout()); Config.setProperty("jcifs.netbios.cachePolicy", getCachePolicy()); Config.setProperty("jcifs.smb.lmCompatibility", getLmCompatibility()); Config.setProperty("jcifs.smb.client.useExtendedSecurity", getUseExtendedSecurity()); Config.setProperty("jcifs.http.domainController", getDomainController()); Config.setProperty("jcifs.smb.client.domain", getDomain()); } @Override public void afterPropertiesSet() throws Exception { Assert.notNull(domain); Assert.notNull(domainController); init(); } // --------------------------------------------------------------------------------------------- // getter and setter // 为了节约版面不写了 }
三) 完成登录功能,登录还是由安全框架负责,如spring-security或apache-shiro
本文不赘述!
四) 开源软件jcifs的maven坐标
<dependency> <groupId>jcifs</groupId> <artifactId>jcifs</artifactId> <version>1.3.17</version> </dependency>
评论
1 楼
3108493554
2016-03-18
你好 ,有些问题想请教下,加下我qq310849354,你这上面的代码是ntlm验证成功就跳转到项目的主页,验证失败就跳到项目的登录页面是吗?
发表评论
-
SpringMVC杂记(十八) ServletRequestAttributes的应用
2014-02-28 12:38 14137看了一下SpringMVC的源代码,原来SpringMVC也提 ... -
SpringMVC杂记(十七) HandlerMethodArgumentResolver接口应用example
2014-01-24 15:29 12151自从spring3.1 开始就有了这个接口,可以为@Reque ... -
SpringWebflow杂记(一) 框架初探,与SpringMVC的集成
2013-10-23 17:18 1664今日研究了一下SpringWebFlow这个项目,作为Spri ... -
SpringMVC杂记(十六) spring-mvc 与 openid4java
2013-10-12 15:25 3814SpringMVC杂记(十六) spring-mvc 与 op ... -
SpringMVC杂记(十五) spring-mvc controller 的切面
2013-08-01 19:42 6060SpringMVC杂记(十五) spring-mvc cont ... -
Spring集成CXF
2013-06-24 15:53 1522Spring集成CXF 零) jar依赖 <dep ... -
SpringMVC杂记(十四) Ajax方式的JSR303认证
2013-06-13 07:29 4480自己定义一个Exception,用来表示数据绑定失败 im ... -
SpringMVC杂记(十三) 使用FreeMarker作为视图层
2013-06-09 11:55 3348实在没什么好说的,直接上配置文件好了 <bean i ... -
通过spring,javamail,和freemarker集成发送HTML方式的电子邮件
2013-05-30 14:02 4819一) 现在项目中用的javamail和org.springfr ... -
SpringMVC杂记(十一) 使用Excel视图
2013-04-06 16:06 6575SpringMVC杂记(十一) 使用Excel视图 一) 其 ... -
Spring集成junit
2012-12-24 10:43 1452package junit; import org. ... -
BootstrapPlugin - daterangepicker 使用笔记
2012-11-13 12:17 21005BootstrapPlugin - daterangepick ... -
SpringMVC杂记(十) 验证码生成
2012-11-06 10:18 2725以前写过一篇关于这个的博客,现在用SpringMVC了,重写一 ... -
SpringMVC杂记(九) 模拟其他类型(非GET,POST)的请求
2012-10-22 10:49 26311) 以前一个小兄弟问我,SpringMVC是否可以使用很多浏 ... -
SpringMVC杂记(八) 使用阿里巴巴的fastjson
2012-07-21 08:27 102281) 国产开源软件要支持的 <dependency& ... -
ActiveMQ学习笔记(二) JMS与Spring
2012-06-24 10:21 7347上文可见,JMS Native API使用起来不是特别方便。好 ... -
我的SpringSecurity实践
2012-04-08 07:49 8908我的SpringSecurity实践 (一) 数据库与实体类 ... -
SpringMVC杂记(七) Jackson与Hibernate LazyLoding无法正常工作解决办法
2012-03-21 13:35 7000SpringMVC杂记(七) Jackson与Hibernat ... -
SpringMVC杂记(六) 下载文件
2012-03-21 09:04 4214SpringMVC杂记(六) 下载文件 1) jar依赖 ... -
SpringMVC杂记(五) JSR303数据验证
2012-03-16 16:30 12379SpringMVC杂记(五) JSR303数据验证 1) 首 ...
相关推荐
springmvc实现拦截器的使用,通过一个简单的登录的拦截器讲述了拦截器的配置以及如何使用。
自定义注解:SpringBoot中针对SpringMvc自定义注解获取用户登陆信息
主要介绍了springmvc+shiro自定义过滤器的实现方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
在进行web项目的开发时,如果时间让用户自己输入,该怎么处理,SpringMVC的转换器可以处理,但是需要自己定义,如何定义和搭配呢?
SpringMVC自定义多视图,多视图实现
NULL 博文链接:https://panyongzheng.iteye.com/blog/2084629
以Maven构建的聚合项目,使用SpringMVC+Mybatis框架,基于JSP Tag技术的分页标签,详细说明见: http://blog.csdn.net/autfish/article/details/52023143
NULL 博文链接:https://yingzhuo.iteye.com/blog/1453438
SpringMVC利用AOP实现自定义注解记录日志
SSM笔记-SpringMVC的自定义拦截器,简单实现拦截器,只需要跟着步骤写就好了,没有特别要注意的地方
springmvc自定义属性编辑器和参数解析器
文档内有springmvc拦截器的配置
博客地址 : http://blog.csdn.net/baidu_19473529/article/details/79437434
NULL 博文链接:https://yingzhuo.iteye.com/blog/1455438
SpringMVC DispatcherServlet重写、自定义拦截器拦截器源码
springMVC自定义防重复提交,通过标签的方式实现
fengchao111-springmvc-interceptor-master.zip
Spring+SpringMvc+MybatisPlus实现多数据源切换、利用自定义Aop注解,只需要在需要切换数据库的方法上加上注解即可实现、极大避免了代码冗余。
使用spring mvc 和spring security 完成简单的自定义登录