- 浏览: 452372 次
- 性别:
- 来自: 大连
博客专栏
-
《Spring Secur...
浏览量:383296
文章分类
最新评论
-
蒙奇君杰:
必须感谢一番!!!愿开源的态度为更多的人所拥有,所 认同!
关于对《Spring Security3》一书的翻译说明 -
601235723:
bbjavaeye 写道你好,有个问题请教一下我配了<b ...
《Spring Security3》第四章第一部分翻译下(自定义的UserDetailsService) -
bay0902:
中国互联网的脊梁
Spring Security 3全文下载 -
hdcustc:
项目源码下载 微博网盘里的那个依赖文件损坏了啊 能否提供个可 ...
Spring Security 3全文下载 -
i641878506:
楼主辛苦, 可以提供原书的原项目文件的下载么
Spring Security 3全文下载
你是否愿意在密码上添加点salt?
如果安全审计人员检查数据库中编码过的密码,在网站安全方面,他可能还会找到一些令其感到担心的地方。让我们查看一下存储的admin和guest用户的用户名和密码值:
用户名 |
明文密码 |
加密密码 |
admin |
admin |
7b2e9f54cdff413fcde01f330af6896c3cd7e6cd |
guest |
guest |
2ac15cab107096305d0274cd4eb86c74bb35a4b4 |
这看起来很安全——加密后的密码与初始的密码看不出有任何相似性。但是如果我们添加一个新的用户,而他碰巧和admin用户拥有同样的密码时,又会怎样呢?
用户名 |
明文密码 |
加密密码 |
fakeadmin |
admin |
7b2e9f54cdff413fcde01f330af6896c3cd7e6cd |
现在,注意fakeadmin用户加密过后密码与admin用户完全一致。所以一个黑客如果能够读取到数据库中加密的密码,就能够对已知的密码加密结果和admin账号未知的密码进行对比,并发现它们是一样的。如果黑客能够使用自动化的工具来进行分析,他能够在几个小时内破坏管理员的账号。
【鉴于作者本人使用了一个数据库,它里面的密码使用了完全一致的加密方式,我和工程师团队决定进行一个小的实验并查看明文password的SHA-1加密值。当我们得到password的加密形式并进行数据库查询来查看有多少人使用这个相当不安全的密码。让我们感到非常吃惊的是,这样的人有很多甚至包括组织的一个副总。每个用户都收到了一封邮件提示他们选择难以猜到的密码有什么好处,另外开发人员迅速的使用了一种更安全的密码加密机制。】
请回忆一下我们在第三章中提到的彩虹表技术,恶意的用户如果能够访问到数据库就能使用这个技术来确定用户的密码。这些(以及其它的)黑客技术都是使用了哈希算法的结果都是确定的这一特点——即相同的输入必然会产生相同的输出,所以攻击者如果尝试足够的输入,他们可能会基于已知的输入匹配到未知的输出。
一种通用且高效的方法来添加安全层加密密码就是包含salt(这个单词就是盐的意思,但为了防止直译过来反而不好理解,这里直接使用这个单词——译者注)。Salt是第二个明文组件,它将与前面提到的明文密码一起进行加密以保证使用两个因素来生成(以及进行比较)加密的密码值。选择适当的salt能够保证两个密码不会有相同的编码值,因此可以打消安全审计人员的顾虑,同时能够避免很多常见类型的密码暴力破解技术。
比较好的使用salt的实践不外乎以下的两种类型:
l 使用与用户相关的数据按算法来生成——如,用户创建的时间;
l 随机生成的,并且与用户的密码一起按照某种形式进行存储(明文或者双向加密)。(所谓的双向加密two-way encrypte,指的是加密后还可以进行解密的方式——译者注)
如下图就展现了一个简单的例子,在例子中salt与用户的登录名一致:
【需要记住的是salt被添加到明文的密码上,所以salt不能进行单向的加密,因为应用要查找用户对应的salt值以完成对用户的认证。】
Spring Security为我们提供了一个接口o.s.s.authentication.dao.SaltSource,它定义了一个方法根据UserDetails来返回salt值,并提供了两个内置的实现:
l SystemWideSaltSource为所有的密码定义了一个静态的salt值。这与不使用salt的密码相比并没有提高多少安全性;
l ReflectionSaltSource使用UserDetails对象的一个bean属性得到用户密码的salt值。
鉴于salt值应该能够根据用户数据得到或者与用户数据一起存储,ReflectionSaltSource作为内置的实现被广泛使用。
配置salted密码
与前面配置简单密码加密的练习类似,添加支持salted密码的功能也需要修改启动代码和DaoAuthenticationProvider。我们可以通过查看以下的图来了解salted密码的流程是如何改变启动和认证的,本书的前面章节中我们见过与之类似的图:
让我们通过配置ReflectionSaltSource实现salt密码,增加密码安全的等级。
声明SaltSource Spring bean
在dogstore-base.xml文件中,增加我们使用的SaltSource实现的bean声明:
<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource"> <property name="userPropertyToUse" value="username"/> </bean>
我们配置salt source使用了username属性,这只是一个暂时的实现,在后面的练习中将会进行修正。你能否想到这为什么不是一个好的salt值吗?
将SaltSource织入到PasswordEncoder中
我们需要将SaltSource织入到PasswordEncoder中,以使得用户在登录时提供的凭证信息能够在与存储值进行比较前,被适当的salted。这通过在dogstore-security.xml文件中添加一个新的声明来完成:
<authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref="jdbcUserService"> <password-encoder ref="passwordEncoder"> <salt-source ref="saltSource"/> </password-encoder> </authentication-provider> </authentication-manager>
你如果在此时重启应用,你不能登录成功。正如在前面练习中的那样,数据库启动时的密码编码器需要进行修改以包含SaltSource。
增强DatabasePasswordSecurerBean
与UserDetailsService引用类似,我们需要为DatabasePasswordSecurerBean添加对另一个bean的引用(即SaltSource——译者注),这样我们就能够为用户得到合适的密码salt:
public class DatabasePasswordSecurerBean extends JdbcDaoSupport { @Autowired private PasswordEncoder passwordEncoder; @Autowired private SaltSource saltSource; @Autowired private UserDetailsService userDetailsService; public void secureDatabase() { getJdbcTemplate().query("select username, password from users", new RowCallbackHandler(){ @Override public void processRow(ResultSet rs) throws SQLException { String username = rs.getString(1); String password = rs.getString(2); UserDetails user = userDetailsService.loadUserByUsername(username); String encodedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user)); getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword, username); logger.debug("Updating password for username: "+username+" to: "+encodedPassword); } }); } }
回忆一下,SaltSource是要依赖UserDetails对象来生成salt值的。在这里,我们没有数据库行对应UserDetails对象,所以需要请求UserDetailsService(我们的CustomJdbcDaoImpl)的SQL查询以根据用户名查找UserDetails。
到这里,我们能够启动应用并正常登录系统了。如果你添加了一个新用户并使用相同的密码(如admin)到启动的数据库脚本中,你会发现为这个用户生成的密码是不一样的,因为我们使用用户名对密码进行了salt。即使恶意用户能够从数据库中访问密码,这也使得密码更加安全了。但是,你可能会想为什么使用用户名不是最安全的可选salt——我们将会在稍后的一个练习中进行介绍。
增强修改密码功能
我们要完成的另外一个很重要的变化是将修改密码功能也使用密码编码器。这与为CustomJdbcDaoImpl添加bean引用一样简单,并需要changePassword做一些代码修改:
public class CustomJdbcDaoImpl extends JdbcDaoImpl { @Autowired private PasswordEncoder passwordEncoder; @Autowired private SaltSource saltSource; public void changePassword(String username, String password) { UserDetails user = loadUserByUsername(username); String encodedPassword = passwordEncoder.encodePassword (password, saltSource.getSalt(user)); getJdbcTemplate().update( "UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", encodedPassword, username); }
这里对PasswordEncoder和SaltSource的使用保证了用户的密码在修改时,被适当的salt。比较奇怪的是,JdbcUserDetailsManager并不支持对PasswordEncoder和SaltSource的使用,所以如果你使用JdbcUserDetailsManager作为基础进行个性化,你需要重写一些代码。
配置自定义的salt source
我们在第一次配置密码salt的时候就提到作为密码salt,username是可行的但并不是一个特别合适的选择。原因在于username作为salt完全在用户的控制下。如果用户能够改变他们的用户名,这就使得恶意的用户可以不断的修改自己的用户名——这样就会重新salt他们的密码——从而可能确定如何构建一个伪造的加密密码。
更安全做法是使用UserDetails的一个属性,这个属性是系统确定的,用户不可见也不可以修改。我们会为UserDetails对象添加一个属性,这个属性在用户创立时被随机设置。这个属性将会作为用户的salt。
扩展数据库scheama
我们需要salt要与用户记录一起保存在数据库中,所以要在默认的Spring Security数据库schema文件security-schema.sql中添加一列:
create table users( username varchar_ignorecase(50) not null primary key, password varchar_ignorecase(50) not null, enabled boolean not null, salt varchar_ignorecase(25) not null );
接下来,添加启动的salt值到test-users-groups-data.sql脚本中:
insert into users(username, password, enabled, salt) values ('admin',' admin',true,CAST(RAND()*1000000000 AS varchar)); insert into users(username, password, enabled, salt) values ('guest',' guest',true,CAST(RAND()*1000000000 AS varchar));
要注意的是,需要用这些新的语句替换原有的insert语句。我们选择的salt值基于随机数生成——你选择任何随机salt都是可以的。
修改CustomJdbcDaoImpl UserDetails service配置
与本章前面讲到的自定义数据库模式中的步骤类似,我们需要修改从数据库中查询用户的配置以保证能够获得添加的“salt”列的数据。我们需要修改dogstore-security.xml文件中CustomJdbcDaoImpl的配置:
<beans:bean id="jdbcUserService" class="com.packtpub.springsecurity.security.CustomJdbcDaoImpl"> <beans:property name="dataSource" ref="dataSource"/> <beans:property name="enableGroups" value="true"/> <beans:property name="enableAuthorities" value="false"/> <beans:property name="usersByUsernameQuery"> <beans:value>select username,password,enabled, salt from users where username = ? </beans:value> </beans:property> </beans:bean>
重写基础的UserDetails实现
我们需要一个UserDetails的实现,它包含与用户记录一起存储在数据库中的salt值。对于我们的要求来说,简单重写Spring的标准User类就足够了。要记住的是为salt添加getter个setter方法,这样ReflectionSaltSource密码salter就能够找到正确的属性了。
package com.packtpub.springsecurity.security; // imports public class SaltedUser extends User { private String salt; public SaltedUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, List<GrantedAuthority> authorities, String salt) { super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); this.salt = salt; } public String getSalt() { return salt; } public void setSalt(String salt) { this.salt = salt; } }
我们扩展了UserDetails使其包含一个salt域,如果希望在后台存储用户的额外信息其流程是一样的。扩展UserDetails对象与实现自定义的AuthenticationProvider时经常联合使用。我们将在第六章:高级配置和扩展讲解一个这样的例子。
扩展CustomJdbcDaoImpl功能
我们需要重写JdbcDaoImpl的一些方法,这些方法负责实例化UserDetails对象、设置User的默认值。这发生在从数据库中加载User并复制User到UserDetailsService返回的实例中:
public class CustomJdbcDaoImpl extends JdbcDaoImpl { public void changePassword(String username, String password) { getJdbcTemplate().update( "UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?" password, username); } @Override protected UserDetails createUserDetails(String username, UserDetails userFromUserQuery, List<GrantedAuthority> combinedAuthorities) { String returnUsername = userFromUserQuery.getUsername(); if (!isUsernameBasedPrimaryKey()) { returnUsername = username; } return new SaltedUser(returnUsername, userFromUserQuery.getPassword(),userFromUserQuery.isEnabled(), true, true, true, combinedAuthorities, ((SaltedUser) userFromUserQuery).getSalt()); } @Override protected List<UserDetails> loadUsersByUsername(String username) { return getJdbcTemplate(). query(getUsersByUsernameQuery(), new String[] {username}, new RowMapper<UserDetails>() { public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException { String username = rs.getString(1); String password = rs.getString(2); boolean enabled = rs.getBoolean(3); String salt = rs.getString(4); return new SaltedUser(username, password, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES, salt); } }); } }
createUserDetails和loadUsersByUsername重写了父类的方法——与父类不同的地方在代码列表中已经着重强调出来了。添加了这些变化,你可以重启应用并拥有了更安全、随机的salt密码。你可能会愿意加一些日志和实验,以查看应用运行期间和启动时用户数据加载时的加密数据变化。
要记住的是,尽管在这个例子中说明的是为UserDetails添加一个简单域的实现,这种方式可以作为基础来实现高度个性化的UserDetails对象以满足应用的业务需要。对于JBCP Pets来说,审计人员会对数据库中的安全密码感到很满意——一项任务被完美完成。
发表评论
-
Spring Security 3全文下载
2012-03-15 20:31 20360本书已经翻译完成,提供给大家下载 以下地址为ITEYE的电子 ... -
《Spring Security3》附录翻译(参考资料)
2012-02-13 22:58 6539附录:参考材料 在本附录中, ... -
《Spring Security3》第十三章翻译(迁移到Spring Security 3)
2012-02-13 22:50 5319第十三章 迁移到Spring Security 3 ... -
《Spring Security3》第十二章翻译(Spring Security扩展)
2012-02-13 22:38 7962第十二章 Spring Security扩展 ... -
《Spring Security3》第十一章(客户端证书认证)第二部分翻译
2012-02-13 22:23 4914在Spring Security中配置客户端证书认证 ... -
《Spring Security3》第十一章(客户端证书认证)第一部分翻译
2012-02-13 22:00 6194第十一章 客户端证书认证(Client Cert ... -
《Spring Security3》第十章(CAS)第二部分翻译(CAS高级配置)
2012-01-19 13:07 8626高级CAS配置 ... -
《Spring Security3》第十章(CAS)第一部分翻译(CAS基本配置)
2012-01-19 12:54 12320第十章 使用中心认证服务(CAS)进行单点登录 ... -
《Spring Security3》第九章(LDAP)第三部分翻译(LDAP明确配置)
2012-01-19 12:44 6445明确的LDAP bean配置 ... -
《Spring Security3》第九章(LDAP)第二部分翻译(LDAP高级配置)
2012-01-19 12:36 7176LDAP的高级配置 一旦我们 ... -
《Spring Security3》第九章(LDAP)第一部分翻译(LDAP基本配置)
2012-01-19 12:22 6172第九章 LDAP目录服务 在本章中,我们 ... -
《Spring Security3》第八章第三部分翻译(属性交换)
2012-01-18 15:46 2928属性交换(Attribute Exchange) ... -
《Spring Security3》第八章第二部分翻译(OpenID用户的注册)
2012-01-18 13:39 5394OpenID用户的注册问 ... -
《Spring Security3》第八章第一部分翻译(OpenID与Spring Security)
2012-01-17 22:38 7560第八章 对OpenID开放 OpenID是 ... -
《Spring Security3》第七章第三部分翻译(ACL的注意事项)
2012-01-17 22:25 2700典型ACL部署所要考虑的事情 ... -
《Spring Security3》第七章第二部分翻译(高级ACL)(下)
2012-01-17 22:17 4198支持ACL的Spring表达式语言 SpEL对A ... -
《Spring Security3》第七章第二部分翻译(高级ACL)(上)
2012-01-10 22:59 4662高级ACL话题 一些高级的话 ... -
《Spring Security3》第七章第一部分翻译(访问控制列表ACL)
2011-12-30 22:02 9490第七章 访问控制列表(ACL) 在本章中, ... -
《Spring Security3》第六章第七部分翻译(认证事件处理与小结)
2011-11-22 22:37 5470认证事件处理 有一个重要的功能只能通 ... -
《Spring Security3》第六章第六部分翻译(Spring Security基于bean的高级配置)
2011-11-22 22:25 5492Spring Security基于bean的高级配置 ...
相关推荐
### Spring Security3 相关知识点概述 #### 第一章:一个不安全应用的剖析 **安全审计** - **目的**:识别系统中的安全隐患,并评估安全措施的有效性。 - **过程**:通过模拟攻击来测试系统的安全性,分析日志记录...
根据给定的信息,我们可以从《Spring Security3 中文版》一书中提炼出多个重要的知识点,主要涉及Spring Security的基础概念、具体实现以及高级配置等方面。下面将详细解释每一部分的关键内容。 ### 第一章:一个不...
### Spring Security3中文文档知识点概览 #### 第一章:一个不安全应用的剖析 - **安全审计**:介绍如何通过安全审计来发现系统中的安全漏洞,并解释审计的重要性。 - **关于样例应用**:本章节以JBCPPets应用为例...
第四部分 Web应用程序安全 112 13.安全过滤器链 112 13.1 DelegatingFilterProxy 112 13.2 FilterChainProxy 113 13.2.1绕过滤网链 115 13.3过滤器排序 115 13.4请求匹配和HttpFirewall 116 13.5与其他基于过滤器的...
#### 第三章:增强用户体验 **自定义登录页** - **实现**:通过配置文件指定自定义的登录页面路径。 - **登录逻辑**:定义表单提交地址,并配置相应的处理器。 **理解退出功能** - **实现**:添加Logout按钮,...
- **OAuth2和OpenID Connect**:如果应用需要支持第三方登录,可以使用OAuth2进行授权,OpenID Connect则是在OAuth2基础上添加了身份验证层。 3. **加密解密模块**: - **对称加密**:使用同一密钥进行加密和解密...
1. 引入相关库:Java的标准库已经包含了MD5的实现,无需额外引入第三方库。首先需要导入`java.security.MessageDigest`和`java.security.NoSuchAlgorithmException`这两个类。 ```java import java.security....
3. **数据加密**:在存储敏感信息如用户密码时,应使用安全的哈希算法如SHA-256,结合盐值(salt)进行加密。对于交易信息,可能需要使用AES(高级加密标准)等对称加密算法,以保护隐私。 4. **身份验证与授权**:...
8. **OAuth2**:一种授权协议,允许第三方应用在用户授权的情况下获取资源。Java可以用`spring-security-oauth2`库实现OAuth2服务器端和客户端的开发。 9. **安全编码**:防止SQL注入、XSS攻击等,Java开发者应该...
- **CSRF(跨站请求伪造)**:防止恶意第三方冒用用户身份进行操作,可以使用CSRF token来验证请求的合法性。 - **XSS(跨站脚本攻击)**:对用户输入进行过滤和转义,避免注入恶意脚本。 6. **会话管理**: - *...
- 实现密码哈希和加盐(salt)以增加安全性,避免明文存储密码。 - 设置会话超时和强制登出,以防止会话固定攻击。 - 对敏感数据进行加密,如用户密码和JWT本身。 - 使用CSRF(跨站请求伪造)防护,防止恶意第三方...
例如,你可以使用C3P0或HikariCP等第三方库来实现连接池功能。在应用程序启动时初始化连接池,并配置最大连接数、超时时间等参数,从而优化数据库访问性能。 #### 6. Java中的异常处理 - **知识点概述**:异常处理...
在Java中,可以集成Google的Authenticator库或使用第三方服务实现。 9. 用户注册和账户管理:除了登录功能,通常还需要用户注册和账户管理功能,包括密码找回、权限修改等。这些都需要与数据库交互,并遵循良好的...
- **安全性设计**:采用Spring Security框架下的BCryptPasswordEncoder加密技术,保障用户信息安全。 ##### 2.2 功能模块 - **用户管理模块**:实现用户注册、登录、个人信息修改等功能。 - **商品展示与搜索**:...
在Java中,可以使用第三方库如Google的reCAPTCHA或者自己实现简单的数学问题验证。 8. **邮箱验证**:为了确认用户邮箱的有效性,通常会发送一封验证邮件,其中包含一个链接让用户点击完成验证。JavaMail API可以...