Springboot+Shiro——MD5盐值加密(配置)
其实这⾥所说的盐,简单的说,就是⼀组安全随机数。它会在特定的时候,加⼊到密码中(⼀般来说是加密后的密码)。从⽽使密码变得更有味道(从单⼀简单化到复杂化),更安全。
如何做到?
1). 在 doGetAuthenticationInfo ⽅法返回值创建 SimpleAuthenticationInfo 对象的时候, 需要使⽤
SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName) 构造器
2). 使⽤ ByteSource.Util.bytes() 来计算盐值.
3). 盐值需要唯⼀: ⼀般使⽤随机字符串或 user id
4). 使⽤ new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations); 来计算盐值加密后的密码的值.
注:下⾯的步骤我重点讲如何配置实现MD5 盐值加密
步骤:
1. 当我们从前台页⾯进⾏登录时,点击提交登录后,在后台通过调⽤Subject的login⽅法,此时shiro会调⽤SecurityManage安全管理器,
尝试对⽐密码并登录,⽽我们要做的就是⾃定义Realm,因为SecurityManage的认证需要从Realm中获取⽤户输⼊的信息。因此需要⾃定义⼀个Realm
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService service;
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection collection){
springboot推荐算法return null;
}
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException {
//通过token获取从前端输⼊的⽤户名
UsernamePasswordToken userToken =(UsernamePasswordToken) token;
String username = Username();
//调⽤service⽅法判断该⽤户名是否存在
User user = service.queryUser(username);
if(user==null){
//抛出⽤户名不存在的错误
throw new UnknownAccountException();
}
//根据⽤户的情况, 来构建 AuthenticationInfo 对象并返回. 通常使⽤的实现类为: SimpleAuthenticationInfo
//通常需要以下四个参数
//1). principal: 认证的实体信息. 可以是 username, 也可以是数据表对应的⽤户的实体类对象.
Object principal = user;
//2). credentials: 密码.即从数据库中获取的密码
Object credentials = Password();
//3). realmName: 当前 realm 对象的 name. 调⽤⽗类的 getName() ⽅法即可
String realmName =getName();
//4). credentialsSalt: 盐值,这⾥我使⽤的是⽤户名
ByteSource credentialsSalt = ByteSource.Util.Name());
return new SimpleAuthenticationInfo(principal,credentials,credentialsSalt,realmName);
}
}
说明:上⾯这个类中的第⼆个⽅法返回的SimpleAuthenticationInfo, 可以理解为⾥⾯传⼊的参数就是⽤于Shiro对⽤户输⼊的密码进⾏认证的相关信息。Shiro会将⽤户输⼊的密码先进⾏MD5 盐值加密再进⾏⽐较。
注:这⾥要注意,你存在数据库中的密码是要加密的,如果没有加密的话,Shiro会认证失败。会报如下错误
[org.apache.shiro.authc.AbstractAuthenticator] - Authentication failed
for token submission [org.apache.shiro.authc.UsernamePasswordToken -
admin01, rememberMe=false]. Possible unexpected error? (Typical or
expected login exceptions should extend from AuthenticationException)
2. 接下来我们就需要配置Shiro,并在⾥⾯配置上使⽤MD5盐值加密
@Configuration
public class ShiroConfig {
/**
* ShiroFilterBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultSecurityManager){
ShiroFilterFactoryBean bean =new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultSecurityManager);
return bean;
}
@Bean("securityManager")
public DefaultWebSecurityManager getDefaultSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager =new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
/**
* 创建 realm 对象 , 需要⾃定义
* @return
*/
@Bean("userRealm")
public UserRealm userRealm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher){
UserRealm userRealm =new UserRealm();
userRealm.setCredentialsMatcher(matcher);
return userRealm;
}
/**
* 替换当前 Realm 的 credentialsMatcher 属性.
* 直接使⽤ HashedCredentialsMatcher 对象, 并设置加密算法即可.
* 密码校验规则HashedCredentialsMatcher
* 这个类是为了对密码进⾏编码的
* 防⽌密码在数据库中明码表⽰,当然在登录认证的时候,
* 这个类也负责对form⾥输⼊的密码进⾏编码
* 处理认证匹配处理器
*/
@Bean("hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher credentialsMatcher =new HashedCredentialsMatcher();
//指定加密⽅式为MD5
credentialsMatcher.setHashAlgorithmName("MD5");
//加密次数
credentialsMatcher.setHashIterations(1024);
return credentialsMatcher;
}
}
3. 在Controller层只需获取当前的 Subject,即调⽤ Subject()。然后把⽤户名和密码封装成封装为
UsernamePasswordToken 对象,最后调⽤Subject 的 login(AuthenticationToken) ⽅法.进⾏认证操作即可
@RequestMapping("/login")
public String login(String username,String password,Model model){
//获取当前的⽤户
Subject subject = Subject();
//封装⽤户的登录数据
UsernamePasswordToken token =new UsernamePasswordToken(username,password);
try{
//执⾏登录⽅法,如果没有异常就Ok
subject.login(token);
return"index";
}catch(UnknownAccountException e){
model.addAttribute("msg","⽤户名错误");
return"login";
}catch(IncorrectCredentialsException e){
model.addAttribute("msg","密码错误");
return"login";
}
}
⾄此关于使⽤MD5 盐值加密的配置就⼤功告成了。
总结⼀下:
Q:如何将获取的密码进⾏MD5 盐值加密:
A:替换当前 Realm 的 credentialsMatcher 属性. 直接使⽤ HashedCredentialsMatcher 对象, 并设置加密算法即可.
Q:如何⽐较⽤户输⼊的密码是否正确
A:通过 AuthenticatingRealm 的 credentialsMatcher 属性来进⾏的密码的⽐对!
1. 获取当前的 Subject. 调⽤ Subject();
2. 测试当前的⽤户是否已经被认证. 即是否已经登录. 调⽤ Subject 的 isAuthenticated()
3. 若没有被认证, 则把⽤户名和密码封装为 UsernamePasswordToken 对象
1). 创建⼀个表单页⾯
2). 把请求提交到 SpringMVC 的 Handler
3). 获取⽤户名和密码.
4. 执⾏登录: 调⽤ Subject 的 login(AuthenticationToken) ⽅法.
5. ⾃定义 Realm 的⽅法, 从数据库中获取对应的记录, 返回给 Shiro.
1). 实际上需要继承 org.alm.AuthenticatingRealm 类
2). 实现 doGetAuthenticationInfo(AuthenticationToken) ⽅法.
6. 由 shiro 完成对密码的⽐对.
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论