当前位置: 首页 > wzjs >正文

给我一个免费网站吗漫画WordPress

给我一个免费网站吗,漫画WordPress,好听的公司名字,吴中快速建设网站价格目录 大纲 一、前言 1. 加密意义 2. 常见方案 2.1. Hash 算法 2.2. 单向自适应函数 二、PasswordEncoder 三、DelegatingPasswordEncoder 1. DelegatingPasswordEncoder源码 2. PasswordEncoderFactories源码 四、如何使用 PasswordEncoder 五、密码加密实战 六、密…

目录

大纲

一、前言

1. 加密意义

2. 常见方案

2.1. Hash 算法

2.2. 单向自适应函数

二、PasswordEncoder

三、DelegatingPasswordEncoder

1. DelegatingPasswordEncoder源码

2. PasswordEncoderFactories源码

四、如何使用 PasswordEncoder

五、密码加密实战

六、密码自动升级


大纲

  • 密码为什么要加密
  • 常见加密的解决方案
  • PasswordEncoder 详解
  • 优雅使用加密

一、前言

1. 加密意义

2011 年12月21 日,有人在网络上公开了一个包含600万个 CSDN 用户资料的数据库,数据全部为明文储

存,包含用户名、密码以及注册邮箱。事件发生后 CSDN 在微博、官方网站等渠道发出了声明,解释说此数据库

系2009 年备份所用,因不明原因泄漏,已经向警方报案,后又在官网发出了公开道歉信。在接下来的十多天里,

金山、网易、京东、当当、新浪等多家公司被卷入到这次事件中。整个事件中最触目惊心的莫过于 CSDN 把用户

密码明文存储,由于很多用户是多个网站共用一个密码,因此一个网站密码泄漏就会造成很大的安全隐患。由于

有了这么多前车之鉴,我们现在做系统时,密码都要加密处理。

在前面的案例中,凡是涉及密码的地方,我们都采用明文存储,在实际项目中这肯定是不可取的,因为这会

带来极高的安全风险。

在企业级应用中,密码不仅需要加密,还需要加盐,最大程度地保证密码安全。

2. 常见方案

2.1. Hash 算法

最早我们使用类似 SHA-256 、SHA-512 、MD5等这样的单向 Hash 算法。用户注册成功后,保存在数据

库中不再是用户的明文密码,而是经过 SHA-256 加密计算的一个字行串,当用户进行登录时,用户输入的明文密

码用 SHA-256 进行加密,加密完成之后,再和存储在数据库中的密码进行比对,进而确定用户登录信息是否有

效。如果系统遭遇攻击,最多也只是存储在数据库中的密文被泄漏。

这样就绝对安全了吗?由于彩虹表这种攻击方式的存在以及随着计算机硬件的发展,每秒执行数十亿次

HASH计算己经变得轻轻松松,

这意味着即使给密码加密加盐也不再安全。

参考: 彩虹表

2.2. 单向自适应函数<Adaptive One-way Functions>

在Spring Security 中,我们现在是用一种自适应单向函数 (Adaptive One-way Functions)来处理密码问

题,这种自适应单向函数在进行密码匹配时,会有意占用大量系统资源(例如CPU、内存等),这样可以增加恶

意用户攻击系统的难度。在Spring Securiy 中,开发者可以通过 bcrypt、PBKDF2、sCrypt 以及 argon2 来体验

这种自适应单向函数加密。由于自适应单向函数有意占用大量系统资源,因此每个登录认证请求都会大大降低应

用程序的性能,但是 Spring Secuity 不会采取任何措施来提高密码验证速度,因为它正是通过这种方式来

增强系统的安全性。

参考 1:用户密码哈希 · libsodium 中文文档

参考 2:https://github.com/xitu/gold-miner/blob/master/TODO1/password-hashing-pbkdf2-scrypt-bcrypt-and-argon2.md

  • BCryptPasswordEncoder
    BCryptPasswordEncoder 使用 bcrypt 算法对密码进行加密,为了提高密码的安全性,bcrypt算法故意降低运行速度,以增强密码破解的难度。同时 BCryptPasswordEncoder “为自己带盐”开发者不需要额外维护一个“盐” 字段,使用 BCryptPasswordEncoder 加密后的字符串就已经“带盐”了,即使相同的明文每次生成的加密字符串都不相同。
  • Argon2PasswordEncoder
    Argon2PasswordEncoder 使用 Argon2 算法对密码进行加密,Argon2 曾在 Password Hashing Competition 竞赛中获胜。为了解决在定制硬件上密码容易被破解的问题,Argon2也是故意降低运算速度,同时需要大量内存,以确保系统的安全性。
  • Pbkdf2PasswordEncoder
    Pbkdf2PasswordEncoder 使用 PBKDF2 算法对密码进行加密,和前面几种类似,PBKDF2
    算法也是一种故意降低运算速度的算法,当需要 FIPS (Federal Information Processing Standard,美国联邦信息处理标准)认证时,PBKDF2 算法是一个很好的选择。
  • SCryptPasswordEncoder
    SCryptPasswordEncoder 使用scrypt 算法对密码进行加密,和前面的几种类似,serypt 也是一种故意降低运算速度的算法,而且需要大量内存。

二、PasswordEncoder

通过对认证流程源码分析得知,实际密码比较是由PasswordEncoder完成的,因此只需要使用

PasswordEncoder 不同实现就可以实现不同方式加密。

public interface PasswordEncoder {String encode(CharSequence rawPassword);boolean matches(CharSequence rawPassword, String encodedPassword);default boolean upgradeEncoding(String encodedPassword) {return false;}
}
  • encode 用来进行明文加密的
  • matches 用来比较密码的方法
  • upgradeEncoding 用来给密码进行升级的方法

默认提供加密算法如下:

三、DelegatingPasswordEncoder

根据上面 PasswordEncoder的介绍,可能会以为 Spring security 中默认的密码加密方案应该是四种自适应

单向加密函数中的一种,其实不然,在 spring Security 5.0之后,默认的密码加密方案其实是

DelegatingPasswordEncoder。

从名字上来看,DelegatingPaswordEncoder 是一个代理类,而并非一种全新的密码加密方案,

DeleggtinePasswordEncoder 主要用来代理上面介绍的不同的密码加密方案。

为什么采DelegatingPasswordEncoder 而不是某一个具体加密方式作为默认的密码加密方案呢?主要考虑了

如下两方面的因素:

  • 兼容性:使用 DelegatingPasswrordEncoder 可以帮助许多使用旧密码加密方式的系统顺利迁移到 Spring security 中,它允许在同一个系统中同时存在多种不同的密码加密方案。
  • 便捷性:密码存储的最佳方案不可能一直不变,如果使用 DelegatingPasswordEncoder作为默认的密码加密方案,当需要修改加密方案时,只需要修改很小一部分代码就可以实现。

1. DelegatingPasswordEncoder源码

public class DelegatingPasswordEncoder implements PasswordEncoder {....
}
  • encode 用来进行明文加密的
  • matches 用来比较密码的方法
  • upgradeEncoding 用来给密码进行升级的方法

2. PasswordEncoderFactories源码

public static PasswordEncoder createDelegatingPasswordEncoder() {String encodingId = "bcrypt";Map<String, PasswordEncoder> encoders = new HashMap<>();encoders.put(encodingId, new BCryptPasswordEncoder());encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());encoders.put("scrypt", new SCryptPasswordEncoder());encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));encoders.put("SHA-256",new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());encoders.put("argon2", new Argon2PasswordEncoder());return new DelegatingPasswordEncoder(encodingId, encoders);}

四、如何使用 PasswordEncoder

  • 查看WebSecurityConfigurerAdapter类中源码
static class LazyPasswordEncoder implements PasswordEncoder {private ApplicationContext applicationContext;private PasswordEncoder passwordEncoder;LazyPasswordEncoder(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic String encode(CharSequence rawPassword) {return getPasswordEncoder().encode(rawPassword);}@Overridepublic boolean matches(CharSequence rawPassword, String encodedPassword) {return getPasswordEncoder().matches(rawPassword, encodedPassword);}@Overridepublic boolean upgradeEncoding(String encodedPassword) {return getPasswordEncoder().upgradeEncoding(encodedPassword);}private PasswordEncoder getPasswordEncoder() {if (this.passwordEncoder != null) {return this.passwordEncoder;}PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);if (passwordEncoder == null) {passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();}this.passwordEncoder = passwordEncoder;return passwordEncoder;}private <T> T getBeanOrNull(Class<T> type) {try {return this.applicationContext.getBean(type);}catch (NoSuchBeanDefinitionException ex) {return null;}}@Overridepublic String toString() {return getPasswordEncoder().toString();}}

通过源码分析得知如果在工厂中指定了PasswordEncoder,就会使用指定PasswordEncoder,

否则就会使用默认DelegatingPasswordEncoder。

五、密码加密实战

  • 测试生成的密码
 @Test
public void test() {//1.BCryptPasswordEncoderBCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();System.out.println(bCryptPasswordEncoder.encode("123"));//2.Pbkdf2PasswordEncoderPbkdf2PasswordEncoder pbkdf2PasswordEncoder = new Pbkdf2PasswordEncoder();System.out.println(pbkdf2PasswordEncoder.encode("123"));//3.SCryptPasswordEncoder //需要额外引入依赖SCryptPasswordEncoder sCryptPasswordEncoder = new SCryptPasswordEncoder();System.out.println(sCryptPasswordEncoder.encode("123"));//4.Argon2PasswordEncoder //需要额外引入依赖Argon2PasswordEncoder argon2PasswordEncoder = new Argon2PasswordEncoder();System.out.println(argon2PasswordEncoder.encode("123"));
}
  • 使用固定密码加密方案
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Beanpublic PasswordEncoder BcryptPasswordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();inMemoryUserDetailsManager.createUser(User.withUsername("root").password("$2a$10$WGFkRsZC0kzafTKOPcWONeLvNvg2jqd3U09qd5gjJGSHE5b0yoy6a").roles("xxx").build());return inMemoryUserDetailsManager;}
}
  • 使用灵活密码加密方案 推荐
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();inMemoryUserDetailsManager.createUser(User.withUsername("root").password("{bcrypt}$2a$10$WGFkRsZC0kzafTKOPcWONeLvNvg2jqd3U09qd5gjJGSHE5b0yoy6a").roles("xxx").build());return inMemoryUserDetailsManager;}
}

六、密码自动升级

推荐使用DelegatingPasswordEncoder 的另外一个好处就是自动进行密码加密方案的升级,这个功能在整合一些

老的系统时非常有用。

  • 准备库表
-- 用户表
CREATE TABLE `user`
(`id`                    int(11) NOT NULL AUTO_INCREMENT,`username`              varchar(32)  DEFAULT NULL,`password`              varchar(255) DEFAULT NULL,`enabled`               tinyint(1) DEFAULT NULL,`accountNonExpired`     tinyint(1) DEFAULT NULL,`accountNonLocked`      tinyint(1) DEFAULT NULL,`credentialsNonExpired` tinyint(1) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- 角色表
CREATE TABLE `role`
(`id`      int(11) NOT NULL AUTO_INCREMENT,`name`    varchar(32) DEFAULT NULL,`name_zh` varchar(32) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- 用户角色关系表
CREATE TABLE `user_role`
(`id`  int(11) NOT NULL AUTO_INCREMENT,`uid` int(11) DEFAULT NULL,`rid` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY   `uid` (`uid`),KEY   `rid` (`rid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
  • 插入数据
-- 插入用户数据
BEGIN;INSERT INTO `user`VALUES (1, 'root', '{noop}123', 1, 1, 1, 1);INSERT INTO `user`VALUES (2, 'admin', '{noop}123', 1, 1, 1, 1);INSERT INTO `user`VALUES (3, 'blr', '{noop}123', 1, 1, 1, 1);
COMMIT;
-- 插入角色数据
BEGIN;INSERT INTO `role`VALUES (1, 'ROLE_product', '商品管理员');INSERT INTO `role`VALUES (2, 'ROLE_admin', '系统管理员');INSERT INTO `role`VALUES (3, 'ROLE_user', '用户管理员');
COMMIT;
-- 插入用户角色数据
BEGIN;INSERT INTO `user_role`VALUES (1, 1, 1);INSERT INTO `user_role`VALUES (2, 1, 2);INSERT INTO `user_role`VALUES (3, 2, 2);INSERT INTO `user_role`VALUES (4, 3, 3);
COMMIT;
  • 整合 mybatis
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version>
</dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version>
</dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version>
</dependency>
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/security?characterEncoding=UTF-88&serverTimezone=UTC&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
mybatis.mapper-locations=classpath:/mapper/*.xml
mybatis.type-aliases-package=com.baizhi.entity
logging.level.com.baizhi.dao=debug
  • 编写实体类
public class User implements UserDetails {private Integer id;private String username;private String password;private Boolean enabled;private Boolean accountNonExpired;private Boolean accountNonLocked;private Boolean credentialsNonExpired;private List<Role> roles = new ArrayList<>();@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {List<SimpleGrantedAuthority> authorities = new ArrayList<>();for (Role role : roles) {authorities.add(new SimpleGrantedAuthority(role.getName()));}return authorities;}@Overridepublic String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String getUsername() {return username;}public void setUsername(String username) {this.username = username;}@Overridepublic boolean isAccountNonExpired() {return accountNonExpired;}public void setAccountNonExpired(Boolean accountNonExpired) {this.accountNonExpired = accountNonExpired;}@Overridepublic boolean isAccountNonLocked() {return accountNonLocked;}public void setAccountNonLocked(Boolean accountNonLocked) {this.accountNonLocked = accountNonLocked;}@Overridepublic boolean isCredentialsNonExpired() {return credentialsNonExpired;}public void setCredentialsNonExpired(Boolean credentialsNonExpired) {this.credentialsNonExpired = credentialsNonExpired;}@Overridepublic boolean isEnabled() {return enabled;}public void setEnabled(Boolean enabled) {this.enabled = enabled;}public void setRoles(List<Role> roles) {this.roles = roles;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}
}
public class Role {private Integer id;private String name;private String nameZh;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getNameZh() {return nameZh;}public void setNameZh(String nameZh) {this.nameZh = nameZh;}
}
  • 创建dao
@Mapper
public interface UserDao {List<Role> getRolesByUid(Integer uid);User loadUserByUsername(String username);Integer updatePassword(@Param("username") String username,@Param("password") String password);
}
  • 编写 mapper
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.baizhi.dao.UserDao"><select id="loadUserByUsername" resultType="User">select id,username,password,enabled,accountNonExpired,accountNonLocked,credentialsNonExpiredfrom `user`where username = #{username}</select><select id="getRolesByUid" resultType="Role">select r.id,r.name,r.name_zh nameZhfrom `role` r,`user_role` urwhere r.id = ur.ridand ur.uid = #{uid}</select><update id="updatePassword">update `user` set password=#{password}where username=#{username}</update></mapper>
  • 编写service 实现
@Service
public class MyUserDetailService implements UserDetailsService,UserDetailsPasswordService {private final UserDao userDao;@Autowiredpublic MyUserDetailService(UserDao userDao) {this.userDao = userDao;}@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userDao.loadUserByUsername(username);if (ObjectUtils.isEmpty(user)) {throw new RuntimeException("用户不存在!");}user.setRoles(userDao.getRolesByUid(user.getId()));return user;}@Overridepublic UserDetails updatePassword(UserDetails user, String newPassword) {Integer result = userDao.updatePassword(user.getUsername(), newPassword);if (result == 1) {((User) user).setPassword(newPassword);}return user;}
}
  • 配置securityconfig
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {private final MyUserDetailService myUserDetailService;@Autowiredpublic SecurityConfig(MyUserDetailService myUserDetailService) {this.myUserDetailService = myUserDetailService;}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//查询数据库auth.userDetailsService(myUserDetailService);}}
  • 启动项目测试

文章转载自:

http://Uw7iLBqT.cffwm.cn
http://Ly7O5Wzd.cffwm.cn
http://YYPtdNn7.cffwm.cn
http://DOEgEX87.cffwm.cn
http://aFfbjuA7.cffwm.cn
http://0Sov0iLA.cffwm.cn
http://YnpivfUS.cffwm.cn
http://okhgUh72.cffwm.cn
http://1GzRCQFU.cffwm.cn
http://OgWMslu0.cffwm.cn
http://5ZLF5vMY.cffwm.cn
http://rWDco8MQ.cffwm.cn
http://BVyy6rtd.cffwm.cn
http://I2iH91j7.cffwm.cn
http://Wo6nZ0z9.cffwm.cn
http://GIGsQt5K.cffwm.cn
http://LCJYzODR.cffwm.cn
http://sJ1A0EYm.cffwm.cn
http://PueNhyu1.cffwm.cn
http://JHSz3TgH.cffwm.cn
http://hlK9Yd73.cffwm.cn
http://W8ZHfM86.cffwm.cn
http://vaKpUaep.cffwm.cn
http://JbqXE6tV.cffwm.cn
http://eTQ8fr36.cffwm.cn
http://pm1rCHgy.cffwm.cn
http://ouZDNtbb.cffwm.cn
http://oBVSEDoW.cffwm.cn
http://8ubBpff6.cffwm.cn
http://PfcoHdIl.cffwm.cn
http://www.dtcms.com/wzjs/651685.html

相关文章:

  • 专业做网站制作的公司做软件常用的网站有哪些
  • 一个完整的企业网站怎么做制作图网老版
  • 移动网站开发的视频下载做网站找谷谷网络比较好
  • 网站建设首页该放什么arttemplate做电商网站
  • 做外贸商城网站个人网站注册费用
  • 深圳网站建设ejaket更改wordpress链接数据库
  • 营销型企业网站核心大前端网站
  • 网站开发技术是什么专业会的wordpress页面怎么编辑
  • 做网站怎么发布wordpress123页
  • 网站使用的主色调专业建站
  • 广州有做虚拟货币网站品牌创建策划方案
  • 东莞网站建设公司服务平台全国建设通官网
  • 有口碑的网站建设公司永久免费网站怎么创建
  • 网站获取客户信息需要备案吗wordpress仿百度贴吧
  • 企业网站psd模板分销商城开发公司
  • 网站开发美工总结php 视频播放网站开发
  • 佛山网站排名wordpress执行流程
  • 做互联网推广的公司搜索引擎优化的主要策略
  • 延吉 网站建设南京老牌网站建设公司
  • 公司网站怎么发布文章山东网站建设团队
  • 湛江网站优化青岛苍南网站建设
  • 做网站怎么赚钱吗营销型网站设计方针
  • 做兼职设计去哪个网站迅捷流程图在线制作网站
  • 网站建设 创业wordpress博客主题自媒体
  • 网页网站的区别是什么建筑工程网价是什么意思
  • 静态网站更新单页加盟网站模板
  • 套模板网站价格wordpress html插件安装
  • 太原网站优化怎么做wordpress模板用法
  • 高埗做网站公司网站结构优点
  • 德阳城乡建设部网站首页常州互联网公司排名