[首页]
[文章]
[教程]
首页
Web开发
Windows开发
编程语言
数据库技术
移动平台
系统服务
微信
设计
布布扣
其他
数据分析
首页
>
编程语言
> 详细
<Web> spring security翻译
时间:
2015-05-18 16:26:02
阅读:
330
评论:
0
收藏:
0
[点我收藏+]
第一步就是创建java配置,配置就是创建一个Servlet Filter,也就是springSecurityFilterChain,它负责处理应用中的所有spring security事物(保护url,验证用户名密码,重定向到登录表单)。
configureGlobal方法名不重要,重要的是需要在有@EnableWebSecurity、@EnableGlobalMethodSecurity、@EnableGlobalAuthentication等注解的类下配置AuthenticationManagerBuilder,否则导致不可预知的结果。
上面这个配置看起来没多少,但是做的工作却很多,如下:
要求认证每一个url
为你生成一个登录表单
允许用户通过user、password来通过验证
允许用户登出
防止CSRF攻击
固定Session保护
集成Security Header
集成Servlet API method
第二步注册springSecurityFilterChain,这个在servlet 3.0环境下可以通过Spring‘s WebApplicationInitializer support来做java配置。当然,Spring Security提供了一个基类AbstractSecurityWebApplicationInitializer,它将保证springSecurityChain被注册。但是使用AbstractSecurityWebApplicationInitializer的时候要分两种情况:
项目中没有使用到springMVC或Spring而想用SpringSecurity的话,你需要传递Security Config到父类中,来保证配置被加载。如下:
这里做了以下事情:
自动注册springSecurityFilterChain Filter
添加ContextLoadListener来加载Security Config
如果已经使用了springMVC,我们只需要这样:
到现在我们的Spring Security只知道如何去验证用户,那么如何让它知道我们需要验证所有用户呢?如何让它知道我们需要基于表单的验证呢?这个问题在于WebSecurityConfigurerAdapter的configure方法中,它提供了一个HttpSecurity来帮助我们配置相应需求:
默认的配置如下:
保证到应用的请求都必须被验证
允许用户通过基于表单的登录验证
允许用户验证Http的基本验证
要注意这里的and()方法,它让我们可以更好的配置http,看源码就可以知道。
可以注意到登录表单是从哪来的,因为还没有提到过任何html或jsp呢,由于spring Security的默认配置没有明确地为登录页面设置url,spring Security会自动生成一个,但是一般是自定义的登录界面,那么可以通过controller来指向它:
我们现在只是要求用户被验证,并且每一个url也被验证。我们可以指定为url子目录添加特别的需求:
如上就是为http提供了多个子验证模块
结构和实现
核心组件:
SecurityContextHolder--这是最基本的对象,我们在这里存储应用的Security Context,包涵了应用中用户的安全验证细节。SecurityContextHolder默认使用ThreadLocal(使得每一个线程保持各自独立的对象,通过set来设置,get来获取)来存储这些细节,这就意味着在该线程中,security context可以被每一个方法访问到,即使Security contex没有作为参数被明确传递给该方法。这样但处理完request的时候,清空线程也会是安全的,当然这都不需要使用者来关心。但是有些应用不太适合用ThreadLocal,因为它们有特定的使用线程方式,比如一个Swing的客户端需要让JVM中的所有线程使用相同的Security context。启动时,可以通过策略来指定你需要的SecurityContextHolder存储方式。然而大多数情况下,我们是不需要修改默认存储策略的。
Authentication--在SecurityContextHolder中我们存储的是和应用用户交互的信息,spring security使用一个Authentication对象来表述这信息,你不需要自己创建这个对象,但是你经常需要查看这个对象,你可以在你的应用中使用下面这段代码来获取当前被认证的用户:
这个对象可以通过调用SecurityContext的getContext()来获取,这个对象是放在threadlocal里面的。
UserDetailsService--从上面一段代码中,还有一点值得我们注意的是Authentication中包涵了用户,这个用户是一个Object类型,大多数情况下这个类可以被强转成UserDetails对象,UserDetails是spring security的核心接口UserDetails,它表述的是一个用户信息,但是是可扩展的并且是基于应用特定的。将UserDetails看作是一个数据库适配器,spring security想要从SecurityContextHolder中获取什么信息,就找UserDetails就行了,作为一个用户数据库,你一般会将UserDetails再次强转成你的用户对象,这样你就可以调用特定的业务方法,如:getEmail(),getUserId()等等。
现在,你可能会疑惑,什么时候提供UserDetails呢,我怎么提供呢,答案就是UserDetailsService,这个接口有一个唯一的方法就是通过获取一个用户名字符串参数来返回UserDetails:
这个是在spring security中获取用户信息最常用的方法。
一旦成功验证用户,那么UserDetails就会被用于在SecurityContextHolder中创建一个Authentication对象,好消息是我们已经有了一系列的UserDetailsService实现类,包括使用了内存map(InMemoryDaoImpl)和使用JDBC的(JdbcDaoImpl),有很多人喜欢用他们自己的实现类,他们自己的实现其实也只基于他们自己的用户系统而已,
GrantedAuthority--除了用户信息,Authentication还有一个重要的方法getAuthorities(),它用来提供一个GrantedAuthority对象数组,GrantedAuthority是授权给用户的权限,也被叫做角色
认证
spring security到底干了什么
保证用户操作是登录过的
用户名密码是正确的
用户的上下问信息是被包涵的
用户的安全上下文是被创建的
权限是被授予的
现在我们来复现一下认证过程:
你访问一个网站的首页,点击连接
请求发送到服务器,服务器发现这是个被保护的资源
由于你没有被授权,服务器需要将你没有权限的信息返回给你,可以http的错误信息,也可以是自定义的错误页面
根据验证机制,你的浏览器会重定向到一个登录页面以便你完成登录信息填写,或者浏览器会直接填写你的表单(cookie)
浏览器再次发送给服务器,信息既可以是用户POST的表单信息,也可以是包涵你验证细节的http头部
然后服务器会检测当前验证信息是否正确,如果正确,会进入第7步,如果错误,一般会返回错误信息以便再次填写表单
会再次请求你最开的连接,如果你的足够的权限来访问到这个资源,那么请求成功,如果没有,你会收到403错误信息
上面顺序的绝大部分spring security都提供了相应的类来对应处理,主要有ExceptionTranslationFilter,AuthenticationEntryPoint和AuthenticationManager的验证机制。
ExceptionTranslationFilter--是一个spring security的过滤器,用来检测spring security的任何异常抛出,异常主要由AbstractSecurityInterceptor抛出,它是验证服务的主要提供者。
AuthenticationEntryPoint--是认证过程中的第三步,每个应用都会提供它自己的认证机制,那么每一个认证机制有他们自己的AuthenticationEntryPoint实现。
认证机制--一旦你的浏览器提交你的认证信息,也就是第六步,当验证机制取回所有Authentication对象,如果验证成功,会将Authentication对象放入SecurityContextHolder,然后再次启动源请求,否则AuthenticationManager拒绝请求,验证机制会向浏览器要求再次发送认证信息
在请求中间存储SecurityContext,略
本地化
spring security支持异常信息的本地化,以便用户更好地理解,如果你的应用是为英语用户提供的,那就不需要了。
所有的异常信息都可以被本地化,包括认证失败和授权失败,异常和日志信息
核心服务
AuthenticationManager--是一个接口,我们可以实现任何我们想做的事,实际上如何操作?如果我们需要检查多个验证数据库呢?默认实现是ProviderManager,比起自己处理认证请求,它将这部分工作移交给了一系列的AuthencationProvider,每一个都会被用于验证,每一个Provider都可抛出异常,也可以返回一个完全填充的Authencation对象,还记的UserDetails和UserDetailsService吗?如果不记得就返回去看看。验证请求最通常的做法就是获取到相应的UserDetails并检查获取到的密码和用户输入的密码,这就是AuthencationProvider的做法,而UserDetails对象和他的权限组会被完全填充到Authencation对象中,并保存在SecurityContext中。如果是基于namespace的配置,可以如下:
在这里,我们提供了3个Provider,他们会按显示的顺序来验证,如果或者通过return null 来跳过验证,如果所有Provider都返回null,那么ProviderManager会返回一个ProviderNotFoundException,你们可以到ProviderManager的JavaDoc中查看更详细的关于provider chain的信息。
ProviderManager--验证机制会在filter会注入一个ProviderManager的引用,并调用它来验证请求。你需要的provider是可以互换的,默认地,spring security会通过ProviderManager来清空Authencation对象中任何敏感的认证信息,防止像密码这样的信息存在的时间大于它可作用的时间。这样做会带来一个问题:如果在Authencation中使用了缓存,缓存中有UserDetails对象的引用,那么移除它的认证信息,那么这个对象就不能再次验证对象中的缓存了,你需要将它复制一份到你的缓存中。还有一种办法就是ProviderManager.eraseCredentialsAfterAuthentication()设为false
DaoAuthenticationProvider--这是spring security提供的AuthencationProvider接口最简单的实现类,也是被最容易被框架兼容的。它利用一个UserDetailsService(作为DAO)来查找用户名,密码,权限组,它只是简单地验证从用户提交信息中包装成的UsernamePasswordAuthenticaionToken中的密码和UserDetailsService中的密码,配置也很简单:
UserDetailsService--上面已经提到过,所有Provider都要用到UserDetailsService接口和UserDetails,UserDetailsService中只有唯一的一个方法,就是UserDetails loadUserByUsername(String username) throws UsernameNotFoundException。
In-Memory Authentication--用来创建一个自定义的UserDetailsService实现类,选择从持久层获取信息,但是大多数应用无需这么复杂。
JdbcDaoImpl--spring security也包括一个从jdbc数据源来认证的UserDetailsService,内部使用了springJDBC,就避免了复杂的ORM来存储用户信息,如果你的应用用到了ORM工具,你就需要自己来实现UserDetailsService来重用或许已经创建好的映射文件:
通过修改DriverManagerDataSource信息,你可以使用不同的关系数据库。
密码编码
spring security的PasswordEncoding接口用来支持持久化密码时的编码工作,我们绝不应该直接将原文密码直接持久化,一般都是利用单向哈希算法(将任意长度的二进制值映射成一个固定长度的二进制值,这个小的二进制值被称为哈希值,它是一段数据的唯一表现形式,要找到两个散列为同一个值的输入,在计算上几乎不可能,所以它可以用来快速查找和加密),如bcrypt,
<Web> spring security翻译
原文:http://www.cnblogs.com/yl0822/p/4511838.html
踩
(
0
)
赞
(
0
)
举报
评论
一句话评论(
0
)
登录后才能评论!
分享档案
更多>
2021年09月23日 (328)
2021年09月24日 (313)
2021年09月17日 (191)
2021年09月15日 (369)
2021年09月16日 (411)
2021年09月13日 (439)
2021年09月11日 (398)
2021年09月12日 (393)
2021年09月10日 (160)
2021年09月08日 (222)
最新文章
更多>
2021/09/28 scripts
2022-05-27
vue自定义全局指令v-emoji限制input输入表情和特殊字符
2022-05-27
9.26学习总结
2022-05-27
vim操作
2022-05-27
深入理解计算机基础 第三章
2022-05-27
C++ string 作为形参与引用传递(转)
2022-05-27
python 加解密
2022-05-27
JavaScript-对象数组里根据id获取name,对象可能有children属性
2022-05-27
SQL语句——保持现有内容在后面增加内容
2022-05-27
virsh命令文档
2022-05-27
教程昨日排行
更多>
1.
list.reverse()
2.
Django Admin 管理工具
3.
AppML 案例模型
4.
HTML 标签列表(功能排序)
5.
HTML 颜色名
6.
HTML 语言代码
7.
jQuery 事件
8.
jEasyUI 创建分割按钮
9.
jEasyUI 创建复杂布局
10.
jEasyUI 创建简单窗口
友情链接
汇智网
PHP教程
插件网
关于我们
-
联系我们
-
留言反馈
- 联系我们:wmxa8@hotmail.com
© 2014
bubuko.com
版权所有
打开技术之扣,分享程序人生!