spring security 控制用户信息用户加密 缓存用户信息
1. MD5加密
任何一个正式的企业应用中,都不会在数据库中使用明文来保存密码的,我们在之前的章节中都是为了方便起见没有对数据库中的用户密码进行加密,这在实际应用中是极为幼稚的做法。可以想象一下,只要有人进入数据库就可以看到所有人的密码,这是一件多么恐怖的事情,为此我们至少要对密码进行加密,这样即使数据库被攻破,也可以保证用户密码的安全。
最常用的方法是使用MD5算法对密码进行摘要加密,这是一种单项加密手段,无法通过加密后的结果反推回原来的密码明文。
首先我们要把数据库中原来保存的密码使用MD5进行加密:
<authentication-provider>
<password-encoder hash="md5"/>
<jdbc-user-service data-source-ref="dataSource"/>
</authentication-provider>
启用MD5算法。用户登录时,输入的密码是明文,需要使用password-encoder将明文转换成md5形式,然后再与数据库中的已加密密码进行比对。
这些配置对普通客户不会造成任何影响,他们只需要输入自己的密码,Spring Security会自动加以演算,将生成的结果与数据库中保存的信息进行比对,以此来判断用户是否可以登陆。
这样,我们只添加了一行配置,就为系统带来了密码加密的功能。
2. 盐值加密
上面的实例在现实使用中还存在着一个不小的问题。虽然md5算法是不可逆的,但是因为它对同一个字符串计算的结果是唯一的,所以一些人可能会使用“字典攻击”的方式来攻破md5加密的系统[5]。这虽然属于暴力解密,却十分有效,因为大多数系统的用户密码都不回很长。
实际上,大多数系统都是用admin作为默认的管理员登陆密码,所以,当我们在数据库中看到“21232f297a57a5a743894a0e4a801fc3”时,就可以意识到admin用户使用的密码了。因此,md5在处理这种常用字符串时,并不怎么奏效。
为了解决这个问题,我们可以使用盐值加密“salt-source”。
修改配置文件:
<authentication-provider>
<password-encoder hash="md5">
<salt-source user-property="username"/>
</password-encoder>
<jdbc-user-service data-source-ref="dataSource"/>
</authentication-provider>
盐值的原理非常简单,就是先把密码和盐值指定的内容合并在一起,再使用md5对合并后的内容进行演算,这样一来,就算密码是一个很常见的字符串,再加上用户名,最后算出来的md5值就没那么容易猜出来了。因为攻击者不知道盐值的值,也很难反算出密码原文。
3. 用户信息缓存
介于系统的用户信息并不会经常改变,因此使用缓存就成为了提升性能的一个非常好的选择。Spring Security内置的缓存实现是基于ehcache的,为了启用缓存功能,我们要在配置文件中添加相关的内容。
<authentication-provider>
<password-encoder hash="md5">
<salt-source user-property="username"/>
</password-encoder>
<jdbc-user-service data-source-ref="dataSource" cache-ref="userCache"/>
</authentication-provider>
我们在jdbc-user-service部分添加了对userCache的引用,它将使用这个bean作为用户权限缓存的实现。对userCache的配置如下所示:
<beans:bean id="userCache" class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
<beans:property name="cache" ref="userEhCache"/>
</beans:bean> <beans:bean id="userEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<beans:property name="cacheManager" ref="cacheManager"/>
<beans:property name="cacheName" value="userCache"/>
</beans:bean> <beans:bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
EhCacheBasedUserCache是Spring Security内置的缓存实现,它将为jdbc-user-service提供缓存功能。它所引用的userEhCache来自spring提供的EhCacheFactoryBean和EhCacheManagerFactoryBean,对于userCache的缓存配置放在ehcache.xml中:
<ehcache>
<diskStore path="java.io.tmpdir"/> <defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/> <cache
name="userCache"
maxElementsInMemory="100"//内存中最多存放100个对象
eternal="false"//不是永久缓存
timeToIdleSeconds="600"//最大空闲时间是600s
timeToLiveSeconds="3600"//最大活动时间是3600s
overflowToDisk="true"//如果内存对象溢出则保存到磁盘
/>
</ehcache>
如果想了解有关ehcache的更多配置,可以访问它的官方网站http://ehcache.sf.net/。
这样,我们就为用户权限信息设置好了缓存,当一个用户多次访问应用时,不需要每次去访问数据库了,ehcache会将对应的信息缓存起来,这将极大的提高系统的相应速度,同时也避免数据库符合过高的风险。
注意
cache-ref隐藏着一个陷阱,如果不看代码,我们也许会误认为cache-ref会在JdbcUserDetailsManager中设置对应的userCache,然后只要直接执行JdbcUserDetailsManager中的方法,就可以自动维护用户缓存。
可惜,cache-ref实际上是在JdbcUserDetailsManager的基础上,生成了一个CachingUserService,这个CachedUserDetailsService会拦截loadUserByUsername()方法,实现读取用户信息的缓存功能。我们在cache-ref中引用的UserCache实际上是放在CacheUserDetailsService中,而不是放到了原有的JdbcUserDetailsManager中,这就会导致JdbcUserDetailsManager中对用户缓存的操作全部失效。
4. 获取当前用户信息
如果只是想从页面上显示当前登陆的用户名,可以直接使用Spring Security提供的taglib。
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<div>username : <sec:authentication property="name"/></div>
如果想在程序中获得当前登陆用户对应的对象。
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
如果想获得当前登陆用户所拥有的所有权限。
Collection<GrantedAuthority> authorities = (Collection<GrantedAuthority>) userDetails.getAuthorities();;
关于UserDetails是如何放到SecuirtyContext中去的,以及Spring Security所使用的TheadLocal模式,我们会在后面详细介绍。这里我们已经了解了如何获得当前登陆用户的信息。
spring security 控制用户信息用户加密 缓存用户信息的更多相关文章
- Spring Security——核心类简介——获得登录用户的相关信息
核心类简介 目录 1.1 Authentication 1.2 SecurityContextHolder 1.3 AuthenticationManager和Authenti ...
- Spring Security控制权限
Spring Security控制权限 1,配置过滤器 为了在项目中使用Spring Security控制权限,首先要在web.xml中配置过滤器,这样我们就可以控制对这个项目的每个请求了. < ...
- spring security控制session
spring security控制session本文给你描述在spring security中如何控制http session.包括session超时.启用并发session以及其他高级安全配置. 创 ...
- Spring Security笔记:使用数据库进行用户认证(form login using database)
在前一节,学习了如何自定义登录页,但是用户名.密码仍然是配置在xml中的,这样显然太非主流,本节将学习如何把用户名/密码/角色存储在db中,通过db来实现用户认证 一.项目结构 与前面的示例相比,因为 ...
- (二)spring Security 自定义登录页面与校验用户
文章目录 配置 security 配置下 MVC 自定义登录页面 自定义一个登陆成功欢迎页面 效果图 小结: 使用 Spring Boot 的快速创建项目功能,勾选上本篇博客需要的功能:web,sec ...
- 使用Spring Security控制会话
1.概述 在本文中,我们将说明Spring Security如何允许我们控制HTTP会话.此控件的范围从会话超时到启用并发会话和其他高级安全配置. 2.会话何时创建? 我们可以准确控制会话何时创建以及 ...
- 使用 spring security 中的BcryptPasswordEncoder对象对用户密码进行加密
一.引入security启动器 在子工程中直接引入,不用指定版本号 二.在启动类中把BCryptPasswordEncoder对象注入到容器中 三.在service 层注入 四. 调用encode方法 ...
- Spring Security 入门(1-8)缓存EhCache
- spring security LDAP获取用户信息
很多企业内部使用LDAP保存用户信息,这章我们来看一下如何从LDAP中获取Spring Security所需的用户信息. 首先在pom.xml中添加ldap所需的依赖. <dependency& ...
随机推荐
- 我的 Unity2D 屏幕适配
以下方法纯属我YY,切勿当真!!! 确定一个设计尺寸,比如 devWidth = 960,devHeight = 640, 按照这个尺寸进行设计游戏. 方式一: 不管什么屏幕尺寸,都和设计的尺寸对应. ...
- Loadrunner中参数化实战(1)-Sequential+Each iteration
参数化数据30条: 脚本如下,演示登录,投资,退出操作是,打印手机号: 首先验证Vugen中迭代: Sequential+Each iteration 设置迭代4次Action 结果如下:
- hdu 5446 Unknown Treasure Lucas定理+中国剩余定理
Unknown Treasure Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Other ...
- js高级技巧之高级定时器
实际上,浏览器负责进行排序,指派某段代码在某个时间点运行的优先级. 可以吧js想象成在时间线上运行的. JavaScript中没有任何代码是立刻执行的,但一旦进程空闲则尽快执行. 1.重复的定时器: ...
- WebGL框架 -- three.js
http://segmentfault.com/a/1190000002421007 http://www.cnblogs.com/shawn-xie/archive/2012/08/16/26425 ...
- AOP动态代理解析2-代码织入入口
通过自定义配置完成了对AnnotationAwareAspectJAutoProxyCreator类型的自动注册,那么这个类到底做了什么工作来完成AOP的操作呢?首先我们看看AnnotationAwa ...
- css之overflow
也说css之overflow:细探之下有意想不到的结果 2016-11-5 滴滴出行·DDFE 作者:dolymood overflow 是一个非常常用的 CSS 属性,一般来说会认为很简单,其实细究 ...
- [bzoj1071]组队[单调指针乱搞]
这道题也很感人,主要改了比较久的时间... bzoj第一页的题,居然只过了五百多个人,(我是第512,orzliyicheng是513) 代码不长,但是细节搞了很久,主要sort写错了,晕... 首先 ...
- 通过adb命令打印log
1.adb logcat --打印当前设备上所有日志 2.adb logcat | findstr *** --过滤仅含***的日志 3.adb logcat *:W --过滤打印严重级别W及以上 ...
- poj2612Mine Sweeper
很简单的模拟题目,但在队内赛的时候一直WA了10发...我ca 题目没看懂,也不算,就是我以为摸到地雷他会标星(*) ,但其实还是(x),T_T #include <cstdio> #in ...