- 浏览: 258532 次
- 性别:
- 来自: 苏州
文章分类
- 全部博客 (289)
- java (72)
- oracle (3)
- mysql (5)
- spring (28)
- hibernate (2)
- osgi (0)
- linux (2)
- ExtJs (1)
- jvm (0)
- mybatis (7)
- 分布式 (11)
- MINA (6)
- apache+tomcat (13)
- js+htm (7)
- android (44)
- http (1)
- hbase+hdoop (0)
- memcache (13)
- search (27)
- 部署及性能 (12)
- mongoDB (2)
- 多线程 (12)
- 安全管理验证 (9)
- struts (1)
- webservice (0)
- easyUI (1)
- spring security (16)
- pattern (6)
- 算法 (2)
最新评论
-
lzh8189146:
CommonsHttpSolrServer这个类,现在是不是没 ...
CommonsHttpSolrServer -
xiaochanzi:
我按照你的方法试了下,tomcat6可以发布,但是访问任何网页 ...
基于内嵌Tomcat的应用开发 -
phoneeye:
麻烦你,如果是抄来的文章,请给出来源。谢谢
ant 两则技巧 -
neverforget:
转载不注明出处
Spring Security3.1登陆验证 替换 usernamepasswordfilter -
liang1022:
若不使用eclipse ,如何在命令行下 运行服务端程序 ?
WebService CXF学习(入门篇2):HelloWorld
http://feiyan35488.iteye.com/blog/896733
这一阵子看到了security,很感兴趣。于是研究一下,我在javaeye上查了好多相关的文档,收益匪浅,从入门级的配置问题,到源码级的解读都非常不错,但是还要自己在亲自走一遍流程才踏实。
我看的security 3.0的源码,原因是 security 2.0 的源码没办法通过maven获取到 。
首先 security的控制内容有: url,method,session三种,我项目中用到的只有 url。下面就按url的流程来走。
思路: 使用filter,过滤所有的url 如 /* 这样,并且这个filter应在最前面,道理就不到说了吧。
1》 security使用的 filter是 org.springframework.web.filter.DelegatingFilterProxy类,在spring-web jar中。
@Override
- protected void initFilterBean() throws ServletException {
- // If no target bean name specified, use filter name.
- <span style="color: #ff0000;">if (this.targetBeanName == null) {
- this.targetBeanName = getFilterName();
- }</span>
- // Fetch Spring root application context and initialize the delegate early,
- // if possible. If the root application context will be started after this
- // filter proxy, we'll have to resort to lazy initialization.
- synchronized (this.delegateMonitor) {
- WebApplicationContext wac = findWebApplicationContext();
- if (wac != null) {
- this.delegate = initDelegate(wac);
- }
- }
- }
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
- throws ServletException, IOException {
- // Lazily initialize the delegate if necessary.
- Filter delegateToUse = null;
- synchronized (this.delegateMonitor) {
- if (this.delegate == null) {
- WebApplicationContext wac = findWebApplicationContext();
- if (wac == null) {
- throw new IllegalStateException("No WebApplicationContext found:
- no ContextLoaderListener registered?");
- }
- this.delegate = initDelegate(wac);
- // 该方法中的 代码
- // Filter delegate =<span style="color: #ff0000;"> wac.getBean(getTargetBeanName(), Filter.class);</span>
- }
- delegateToUse = this.delegate;
- }
- // Let the delegate perform the actual doFilter operation.
- invokeDelegate(delegateToUse, request, response, filterChain);
- }
这里需要注意一点 filter-name 必须为 springSecurityFilterChain,从DelegatingFilterProxy这个名字中可以猜到这只是个代理类(确实如此),当这个类执行时会去取得真正的filter类,这个类在spring容器中默认生成id为 springSecurityFilterChain,在3.0中 该filter 添加了一个 targetName 字段,可以从上面红色代码部分看到它的作用,因此可以通过指定targetName字段,来防止和项目中的其他filter冲突。
接下来 该真正的 filterChain出场了,这个类是security事务相关的,应该在security包中。
于是 在 spring-security-web jar中发现了这个类:org.springframeword.security.web.FilterChainProxy ,进去看看可以看出这个就是我要找的类。(关于这一点我是从命名上看出来的,bean的id要和类名保持一致)。
下班了 ,回去再继续添加。
==========================华丽丽的分界线====================================
吃完饭 ,继续。
FilterChainProxy 代码:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
List<Filter> filters = getFilters(fi.getRequestUrl());
// 根据url 得到需要经过的filters
// 这里不是很明白,有知道的同学可以留言。
if (filters == null || filters.size() == 0) { // 如果没有合适的 ,就继续进行filter
if (logger.isDebugEnabled()) {
logger.debug(fi.getRequestUrl() +
filters == null ? " has no matching filters" : " has an empty filter list");
}
chain.doFilter(request, response);
return;
}
//如果有filter 就进行虚拟的filter链。这里并没有跳出容器的 filter链,
// 当这个虚拟的filter链完成之后,就继续进行 容器的filter
VirtualFilterChain virtualFilterChain = new VirtualFilterChain(fi, filters);
virtualFilterChain.doFilter(fi.getRequest(), fi.getResponse());
}
接下来就该进行 filterChain了,在security中有好多的filter:
CHANNEL_FILTER ChannelProcessingFilter
CONCURRENT_SESSION_FILTER ConcurrentSessionFilter
SESSION_CONTEXT_INTEGRATION_FILTER HttpSessionContextIntegrationFilter
LOGOUT_FILTER LogoutFilter
X509_FILTER X509PreAuthenticatedProcessigFilter
PRE_AUTH_FILTER Subclass of AstractPreAuthenticatedProcessingFilter
CAS_PROCESSING_FILTER CasProcessingFilter
AUTHENTICATION_PROCESSING_FILTER AuthenticationProcessingFilter
BASIC_PROCESSING_FILTER BasicProcessingFilter
SERVLET_API_SUPPORT_FILTER classname
REMEMBER_ME_FILTER RememberMeProcessingFilter
ANONYMOUS_FILTER AnonymousProcessingFilter
EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilter
NTLM_FILTER NtlmProcessingFilter
FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptor
SWITCH_USER_FILTER SwitchUserProcessingFilter 。
下面我只分析了 AuthenticationProcessingFilter,这是登录认证处理filter
public UsernamePasswordAuthenticationFilter() {
super("/j_spring_security_check");// 这就是 登录验证的 url。
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} // 只允许以post方法 进行认证,能防止一些简单的破解
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
// 只是将 username和password封装进去
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Place the last username attempted into HttpSession for views
HttpSession session = request.getSession(false);
if (session != null || getAllowSessionCreation()) {
request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextEscapeUtils.escapeEntities(username));
}
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
// 取得AuthenticationManager 进行认证
return this.getAuthenticationManager().authenticate(authRequest);
}
从request中取得 username,password,封装进 UsernamePasswordAuthenticationToken 中,
然后将username中写到 session中,这里对username去掉了首尾的空格
然后调用 AuthenticationManager的 authenticate方法进行具体的认证操作。
public Authentication doAuthentication(Authentication authentication) throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
Authentication result = null;
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
logger.debug("Authentication attempt using " + provider.getClass().getName());
try {
result = provider.authenticate(authentication);
if (result != null) {
copyDetails(authentication, result);
break;
}
} catch (AccountStatusException e) {
// SEC-546: Avoid polling additional providers if auth failure is due to invalid account status
eventPublisher.publishAuthenticationFailure(e, authentication);
throw e;
} catch (AuthenticationException e) {
lastException = e;
}
}
if (result == null && parent != null) {
// Allow the parent to try.
try {
result = parent.authenticate(authentication);
} catch (ProviderNotFoundException e) {
// ignore as we will throw below if no other exception occurred prior to calling parent and the parent
// may throw ProviderNotFound even though a provider in the child already handled the request
} catch (AuthenticationException e) {
lastException = e;
}
}
if (result != null) {
if (eraseCredentialsAfterAuthentication && (result instanceof CredentialsContainer)) {
// Authentication is complete. Remove credentials and other secret data from authentication
((CredentialsContainer)result).eraseCredentials();
}
eventPublisher.publishAuthenticationSuccess(result);
return result;
}
// Parent was null, or didn't authenticate (or throw an exception).
if (lastException == null) {
lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound",
new Object[] {toTest.getName()}, "No AuthenticationProvider found for {0}"));
}
eventPublisher.publishAuthenticationFailure(lastException, authentication);
throw lastException;
}
这里对 用户进行认证,成功就发布成功事件,并返回。 失败就发布失败事件,并返回exception
这里具体的认证过程还是不大熟悉,等再详细的看明白了 再细说。
看明白了,authenticationManager可以有多个 provider如 默认的daoAuthenticationProvider 和 JaasAuth ,RememmberMeAuth 等
下面说 daoAuthenticationProvider 中可以有 UserDetailsService ,
protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
UserDetails loadedUser;
try {
loadedUser = this.getUserDetailsService().loadUserByUsername(username);
}
catch (DataAccessException repositoryProblem) {
throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
}
if (loadedUser == null) {
throw new AuthenticationServiceException(
"UserDetailsService returned null, which is an interface contract violation");
}
return loadedUser;
}
又通过 userDetailsService.loadUserByUsername() ,当不存在时 ,返回null
来得到 UserDetails 这样就能把 整个认证过程理顺了
总结一下, security 的认证过程能理顺了,对其衔接的过渡代码 还有些拿不准,还有 取得filters的 规则还不是很清楚,还要继续看下去。
已经能理顺了, 在BeanId 类中发现了那些默认的字符串,这样 在spring 解析xml时,遇到 security的标签后,会将这个节点交给 security下的类来执行SecurityNamespaceHandler。
这样就能保证security初始化的正常。包括生成默认的 FilterChainProxy 和添加一些依赖。生成 AuthenticationManager及其依赖的 ProviderManager 等。
下次,继续看 url资源控制部分
发表评论
-
在spring security3上实现验证码
2012-04-21 16:07 642在spring security3上实现验证码 h ... -
Spring Security3.1登陆验证 替换 usernamepasswordfilter
2012-04-15 02:01 3404一、前言 在上一篇http://blog.c ... -
Spring Security 3应用的11个步骤
2012-04-15 01:47 1177Spring Security 3应用的11个步骤 ... -
在spring security3上实现验证码
2012-03-01 08:44 621转载: 在spring securi ... -
spring security 密码编码器
2012-03-14 08:13 970spring security 密码编码器 (2 ... -
spring security 配置详解
2012-02-25 11:50 2240http://static.springsource.org/ ... -
图解Spring Security默认使用的过滤器
2012-02-24 08:13 768转载:http://www.flyysoft.com/plus ... -
Spring Security 3 与 CAS单点登录配置-Server
2012-03-15 19:56 1291转载:http://www.hxdw.com/bbs/post ... -
Topic: Spring Security 3 与 CAS单点登录配置-Client
2012-02-26 12:12 816转载: http://www.hxdw.com ... -
Spring Security 可动态授权RBAC权限模块实践
2012-02-19 13:25 2057Spring Security 可动态授权RBA ... -
Spring Security 3 基于角色访问控制过程详解
2012-02-19 13:25 1404访问控制:由于我们配 ... -
修改spring security源码实现动态授权
2012-02-21 08:15 918修改spring security源码实现动态 ... -
spring security 3.0 logout filter 代码中的一个小bug
2012-03-15 19:57 998spring security 3.0 log ... -
spring security 源码分析: 过滤器
2012-03-19 08:23 1006spring security 源码分析: 过 ... -
spring security遇到的一些问题
2012-03-19 08:24 654spring security遇到的一些问题 ...
相关推荐
1. **Spring 事务处理**:Spring 提供了声明式事务管理,允许开发者在配置文件中定义事务边界,无需在业务逻辑代码中显式控制事务开始、提交和回滚。它主要基于AOP代理来实现,通过TransactionInterceptor拦截器进行...
### SpringSecurity企业级认证全套开发资源解析 #### 一、Spring Security概述与核心特性 Spring Security 是一个功能强大且高度可定制的身份验证和安全(ACL)框架。它为基于Spring的应用程序提供了声明式方法的...
SpringSecurity 全套开发,设计源码解读,整个拦截器链分析,QQ登录,微信登录,短信验证,短信登录,在security基础上学习写一个自定义验证授权设计模式,整套视频讲解的分享细致认真,非常值得学习。不管小白还是...
总结起来,《我的SpringSecurity实践》这篇文章可能涵盖了SpringSecurity的源码解析、配置文件的解读,以及在实际项目中如何利用工具进行安全控制。对于想要深入了解SpringSecurity的读者,这是一个很好的学习起点,...
Java springBlade微服务开发平台 是一个由商业级项目升级优化而来的微服务架构,采用Spring Boot 2.6 、Spring Clou,用前后端分离的模式,前端开源两个框架:Sword (基于 React、Ant Design)、Saber (基于 Vue、...
本篇文章将围绕Spring Security实现OAuth2中的密码模式,详细解读其源码,以帮助开发者深入理解这一关键流程。 首先,我们需要明确OAuth2的密码模式(Resource Owner Password Credentials Grant)是如何工作的。在...
### acegi源码解读:深度剖析Spring Security核心组件 #### 引言 在现代Web应用开发中,安全性是至关重要的一个方面。Spring Security作为Spring框架的一部分,提供了强大的安全功能,包括认证、授权、会话管理等...
4. **Hystrix源码解读**:Hystrix是著名的断路器库,用于防止服务雪崩。源码分析可以帮助我们理解断路、短路、回退等机制的实现,以及如何监控和调优。 在实际开发中,我们还需要关注配置管理、熔断策略、监控与...
6. **Spring Security**:这部分源码可能会涵盖Spring的安全管理,如身份验证、授权、CSRF保护等功能。它展示了如何配置和使用Spring Security来保护Web应用的各个部分。 7. **Spring Integration**:源码中可能...
SpringSecurity 全套开发,设计源码解读,整个拦截器链分析,QQ登录,微信登录,短信验证,短信登录,在security基础上学习写一个自定义验证授权设计模式,整套视频讲解的分享细致认真,非常值得学习。
1. **什么是Spring框架?** Spring是一个开源的Java平台,它为构建企业级应用提供了全面的框架支持,包括依赖注入、面向切面编程(AOP)、数据访问、事务管理等。 2. **依赖注入(DI)是什么?** 依赖注入是一种...
此外,源码中还可能涵盖日志管理、安全控制(Spring Security)、缓存支持(如Redis)以及其他Spring Boot集成的第三方服务,如邮件服务、任务调度(Quartz)等。通过实际操作和代码解读,可以提升开发者对Spring ...
9. **源码解读**:部分章节可能涉及Spring框架的源码分析,帮助读者理解其内部工作原理,提高问题排查和性能优化的能力。 10. **PDF格式**:本书以PDF形式提供,方便读者在各种设备上阅读和检索,易于打印和保存。 ...
《Spring源码解析》系列文章深入探讨了Spring框架的核心组件和工作原理,为读者提供了丰富的技术洞察。以下是对这些主题的详细解读: 1. **Spring MVC**:Spring MVC是Spring框架的一部分,它提供了构建Web应用程序...
1. **Spring外文文献**: Spring的外文文献通常涵盖框架的最新发展、最佳实践、设计原则和应用场景。它们可能来自于官方文档、技术博客、学术论文或专业书籍。这些文献能够帮助开发者了解Spring的最新动态,如...
【Jeecms源码解读】 Jeecms是一款基于Java技术的企业级内容管理系统,它提供了丰富的功能,包括内容管理、用户管理、权限控制等,适用于构建各类企业网站、新闻门户等。源码解读对于理解Jeecms的工作原理和进行二次...
描述中提到的博客链接指向了iteye上的一个博客条目,虽然具体内容没有给出,但通常这类资源会提供对Spring源码的分析和解读,帮助开发者理解Spring框架的核心组件和工作流程。可能包括IoC容器、AOP实现、Bean生命...
1. **Spring Security架构**:理解Spring Security的模块化设计,包括核心类如FilterChainProxy、SecurityContextRepository、AuthenticationManager等,以及它们在请求处理流程中的作用。 2. **配置与设置**:学习...
本书将通过详细的案例分析和源码解读,帮助读者深入了解Spring的每个模块,从而在实际项目中更加得心应手地运用Spring框架。通过对这些核心概念的掌握,开发者不仅可以提升个人技术水平,还能提高团队协作效率,实现...