spring-security 登陆认证之初次探究
首先,希望还对 spring-security框架完全不懂的新手 下载下Git源码。 引入到项目中。这个短文就是边看源码边聊的。也会启动下项目验证自己的推想。
一、登陆认证的登陆配置项
<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true" default-target-url="/index.ht"
username-parameter="username" password-parameter="password" login-processing-url="/j_spring_security_check"/>
<logout logout-url="/logout.ht"/>
看到这个配置,其实就大略明白了。 这就像配置了一个control/Servlet, userName 参数名字为 ”name“,password 为”password“
然后校验用户密码,通过就跳转的页面为 index.ht 。
spring-security框架维护了一个过滤器链来提供服务, 而<form-login/> 这个登陆配置项其实创建了一个名为UsernamePasswordAuthenticationFilter的过滤器 。
框架提供的这些过滤器,也包括<custom-filter/>配置的过滤器。都是通过假名有严格顺序来执行的。稍后详细介绍自定义过滤器。
UsernamePasswordAuthenticationFilter :
正如我们配置的这些参数,也会有默认配置的 比如
usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY =“j_username”,
passwordParameter=“j_password”
默认接受form请求地址 :j_spring_security_check ,
这些可配置的参数,都会存在默认参数。这些参数的读取是在 Initializing Spring root WebApplicationContext 后,加载并且解析xml配置文件。然后初始化ioc 容器。形成上面所提的过滤器链。
二、简单说一下解析xml 过程
HttpSecurityBeanDefinitionParser.parse() { filterChains.add(createFilterChain(element, pc)); }
createFilterChain方法会调用 AuthenticationConfigBuilder的构造方法 初始化各种filter createFormLoginFilter(sessionStrategy, authenticationManager); 即为登录配置信息xml的解析处理方法:

SecurityNamespaceHandler.parse(Element element, ParserContext pc) // 关键代码: String name = pc.getDelegate().getLocalName(element);
BeanDefinitionParser parser = parsers.get(name);
通过配置项的名字。以策略模式获取到专用解析器 都实现自BeanDefinitionParser 接口, 通过父类的引用执行子类的具体实现。调用这些子类的parse()方法eg:RememberMeBeanDefinitionParser,LogoutBeanDefinitionParser等、、
错误代码不必看
<form-login/> 的解析在 FormLoginBeanDefinitionParser, 解析后拿到配置的参数,然后初始化一个filter 。
不知道这个解析方法为啥没有实现BeanDefinitionParser 。 本来不想贴代码的。更想愿意读的人自己下载源码自己看。

三、获取登陆获取账号密码
切面走到这个登陆过滤器的时候 UsernamePasswordAuthenticationFilter.attemptAuthentication() 的方法 会从request中,通过配置的userNameParam ,passwordParam 获取 name password
然后构造一个包装了密码账号的对象: new UsernamePasswordAuthenticationToken(password,username)
然后调用接口 AuthenticationManager.authenticate() (认证管理类中的一个实现类 ProviderManager的认证方法)
四、配置验证密码的认证管理类
配置认证管理类 AuthenticationManager 需要 给它提供了一个 user-service bean 来通过用户名获取用户
这个userDetailProvider bean 需要实现 UserDetailsService接口 提供一个 loadUserByUsername()方法。
配置项:
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="userDetailProvider"/>
</security:authentication-manager>
<bean id="userDetailProvider" class="com.hotent.web.security.provider.UserAuthProvider"/>
然后 从ProviderManager 中的 List<AuthenticationProvider> providers认证策略都 拿出来 进行认证(虚)
AbstractUserDetailsAuthenticationProvider .authenticate()
retrieveUser() // 调用子类DaoAuthenticationProvider的实现方法
DaoAuthenticationProvider.retrieveUser() 会通过我之前配置的userDetailProvider.loadUserByUsername(username),获取用户,
然后preAuthenticationChecks.check(user); 校验用户是否可用、锁定、过期
然后调用additionalAuthenticationChecks()方法验证密码。
五、配置 密码加密方式
接着我登陆不上才发现没有配置密码的加密类型。随便找了 个文档。配了下、居然发现启动不了,妹的。
还好我比较机智,找到了xsd校验文件

顺利找到了正确配置方法,在authentication-provider element下、 有一个password-encoder xs:element

这个element 有个attribute<xs:attributeGroup ref="security:password-encoder.attlist"/>,这个想必就是spring-security所支持的所有加密类型了。那xml 就改成了 这样

最终authenticationManager的配置 如下
<security:authentication-manager alias="authenticationManager"><!-- 鉴定管理类 -->
<security:authentication-provider user-service-ref="userDetailProvider">
<security:password-encoder hash="sha-256"/>
</security:authentication-provider>
</security:authentication-manager>
其实很少有人这么傻着从校验文件 去查属性的。 除了像我这种机智到二的人。 其实官方文档说的很清楚,而且xml也会有提示。但是我抱着探究的态度还是直接看xsd。
这样密码加密校验就通过。
接着将成功登陆用户,和用户信息发布出一个事件
applicationEventPublisher.publishEvent(new AuthenticationSuccessEvent(authentication));
///
六、登陆的扩展
很多时候,我们希望做更多的扩展、比如加一些U盾之类的口令啦、短信校验啦。验证码啦。 那么要实现、可以加些自定义的过滤器,也可以重写一些方法,等等、初次探究,我现在还不够清楚。 不过这些都略有些麻烦。
其实如果你自己去校验用户。然后将用户登录信息放入SecurityContext 里面 也就可以随心所欲了。
如下图 验证账号密码、验证码 的截图略过 !直接是验证密码后的操作。

关键代码
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, encrptPassword);
authRequest.setDetails(new WebAuthenticationDetails(request));
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication auth = authenticationManager.authenticate(authRequest);
securityContext.setAuthentication(auth);
sessionStrategy.onAuthentication(auth, request, response);
注入要使用的类
@Resource(name = "authenticationManager")
private AuthenticationManager authenticationManager = null;
@Resource
UserDetailsService userDetailsService;
@Resource
private SessionAuthenticationStrategy sessionStrategy= new NullAuthenticatedSessionStrategy();
注入的authenticationManager 其实就是之前写到的 ProviderManager
我们直接使用用户名,密码(加密后) 构建了UsernamePasswordAuthenticationToken(为存放密码账号信息的一个令牌) 是Authentication接口的一个实例。然后把构建好的 authentication 发送给authenticationManager 进行校验 。
authenticationManager 成功校验后,返回一个完全的 Authentication 实例。
SecurityContextHolder.getContext().setAuthentication(...)
Spring Security 并不知道你怎么把Authentication 对象 放到了SecurityContextHolder 里面,唯一关键点就是 “SecurityContextHolder 已经包含了一个 Authentication 标识了一个主体”。 这样就能满足AbstractSecurityInterceptor 之前的验证一个用户需要。
所以、这个authentication放入SecurityContextHolder的过程可以有很多种方式、一个过滤器、一个control方法、就能达到目的,自然就实现了登陆。
有空继续
spring-security 登陆认证之初次探究的更多相关文章
- 最简单易懂的Spring Security 身份认证流程讲解
最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...
- Spring Cloud实战 | 第九篇:Spring Cloud整合Spring Security OAuth2认证服务器统一认证自定义异常处理
本文完整代码下载点击 一. 前言 相信了解过我或者看过我之前的系列文章应该多少知道点我写这些文章包括创建 有来商城youlai-mall 这个项目的目的,想给那些真的想提升自己或者迷茫的人(包括自己- ...
- Spring Security 接口认证鉴权入门实践指南
目录 前言 SpringBoot 示例 SpringBoot pom.xml SpringBoot application.yml SpringBoot IndexController SpringB ...
- SpringBoot Spring Security 核心组件 认证流程 用户权限信息获取详细讲解
前言 Spring Security 是一个安全框架, 可以简单地认为 Spring Security 是放在用户和 Spring 应用之间的一个安全屏障, 每一个 web 请求都先要经过 Sprin ...
- 学习Spring Boot:(二十八)Spring Security 权限认证
前言 主要实现 Spring Security 的安全认证,结合 RESTful API 的风格,使用无状态的环境. 主要实现是通过请求的 URL ,通过过滤器来做不同的授权策略操作,为该请求提供某个 ...
- Spring Security登陆
本文参考或摘录自:http://haohaoxuexi.iteye.com/blog/2154714 在上一篇中使用Spring Security做了一些安全控制,如Spring Security 自 ...
- 学习Spring Security OAuth认证(一)-授权码模式
一.环境 spring boot+spring security+idea+maven+mybatis 主要是spring security 二.依赖 <dependency> <g ...
- Spring Security 安全认证
Spring Boot 使用 Mybatis 依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> ...
- Spring Security 入门(1-5)Spring Security - 匿名认证
匿名认证 对于匿名访问的用户,Spring Security 支持为其建立一个匿名的 AnonymousAuthenticationToken 存放在 SecurityContextHolder 中, ...
随机推荐
- 汇编test和cmp区别
来自http://tunps.com/assembly-test-and-cmp 看过破解教程,都知道test,cmp是比较关键,可是我一直不清楚它们究竟是怎么比较的,最后下决心找了很多资料,和大家一 ...
- tomcat加入系统服务
在实际的项目开发中web容器等都是安装在客户方的服务器上的,在实现tomcat的集群时为了实现防止客户重启的机器造成服务器的关闭因此需要将web容器加入到系统服务中,在系统启动的时候自动启动服务,以t ...
- WDCP安装memcached
memcached安装 我们打开Web控制面板的时候其实memcached是没有安装的,所以我们要手动安装这个组件. 首先是要下载安装源代码并执行. 1 2 wget -c http://down.w ...
- ecshop有关real_ip()你发现的问题
我这边有一个ECSHOP后台,有一个功能,在客户下订单时自动获取客户IP,用的是ECSHOP本身的real_ip函数,但这个函数存在一个问题,十个订单得到的IP,可能会有几个与CNZZ统计得到的不一样 ...
- python 基础,包括列表,元组,字典,字符串,set集合,while循环,for循环,运算符。
1.continue 的作用:跳出一次循环,进行下一次循环 2.break 跳出不再循环 3.常量 (全是大写)NAME = cjk 一般改了会出错 4.py ...
- bayes
from numpy import * import time starttime = time.time() def loadDataSet(): postingList = [['my', 'do ...
- 《python基础教程》笔记之 基础知识
数字相关 在Python程序前加上 from __future__ import division 或者在解释器里面直接执行它,或者通过命令行运行Python时使用命令开关-Qnew,会使单斜线不再整 ...
- C++服务器linux开发环境管理
在游戏服务器开发中,跨平台不是必须的.线上游戏既有windows下的C++..Net服务器也有linux下的C++.go.erlang服务器.但是无论如何都要保证开发环境和线上运行环境的一致,否则不同 ...
- Mongodb增加权限管理
前言: 随着列式存储理念的成熟,越来越多的开发者开始接纳mongodb,hbase这类大储存的分布式列式数据库.特别是mongodb的这种快速搭建,快速使用特点,使其得到更多人的青睐.本人主要通过官 ...
- Node开发入门
介绍 Node.js采用google的V8虚拟机来解释和执行javascript,也就是允许脱离浏览器环境运行javascript代码. Hello World 婴儿说的第一个字一般是"妈& ...