Shiro 的应用之认证拦挡
Shiro 是一个平安开发框架,它把零碎的平安认证等相干性能抽取进去,升高了零碎的开发成本。
一 Shiro 实现认证拦挡
步骤: 1 零碎调用 subject 的 login 办法将用户信息传递给 securityManager
2 securityManager 将认证操作委托给 Authenticator
3 Authenticator 将用户输出的身份信息发送给 Realm
4 Realm 拜访数据库获取用户信息并将信息封装并返回
5 Authenticator 对封装的信息进行身份认证
输出用户信息后登陆到零碎界面
1. 须要的依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
2. Shiro 的外围配置对象
在 springboot 中没有为咱们主动配置 shiro,所以要手动配置
- 首先创立一个配置类:SpringShiroConfig 类;
- 而后在配置类中增加 SecurityManager 接口对象;
- 在配置类中增加一个 ShiroFilterFactoryBean 对象;通过此对象实现对匿名拜访和认证拜访
- 代码如下:
package com.py.pj.common.config;
import java.util.LinkedHashMap;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author WL
* @version 创立工夫:2020-9-19 13:24:57
* @Description Shiro 的外围配置对象
* @Configuration 此注解形容的类是一个配置对象,此对象会交给 spring 解决
* @Bean 此注解形容的类会被交给 spring 解决,由 spring 为咱们创建对象
*/
@Configuration
public class SpringShiroConfig {
@Bean
public SecurityManager securityManager(Realm realm) {DefaultWebSecurityManager dsm = new DefaultWebSecurityManager();
dsm.setRealm(realm);
return dsm;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {ShiroFilterFactoryBean sffBean = new ShiroFilterFactoryBean();
sffBean.setSecurityManager(securityManager);
// 设置登录界面 url
sffBean.setLoginUrl("/doLogin");
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("/bower_components/**", "anon");
map.put("/modules/**", "anon");
map.put("/dist/**", "anon");
map.put("/plugins/**", "anon");
// 用户登录界面容许匿名拜访
map.put("/user/doLogin", "anon");
// 退出登陆
map.put("/doLogout", "logout");
// 除了动态资源,其余的都要认证
map.put("/**", "authc");
sffBean.setFilterChainDefinitionMap(map);
return sffBean;
}
}
3. 业务模块实现
本模块的业务在 realm 模块中实现
- 3.1 依据用户名搜寻用户信息
在 SysUserMapper 中创立 findUserByUsername(String username) 办法
SysUser findUserByUsername(String username);
mapper 映射文件中
<select id="findUserByUsername" resultType="com.py.pj.sys.entity.SysUser">
select * from sys_users where username=#{username}
</select>
- 3.2 创立 realm 业务层
package com.py.pj.sys.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.py.pj.sys.dao.SysUserMapper;
import com.py.pj.sys.entity.SysUser;
/**
* @author WL
* @version 创立工夫:2020-9-19 14:15:12
* @Description 受权 realm 继承认证,所以蕴含认证和受权性能
*/
@Service
public class ShiroUserRealm extends AuthorizingRealm {
@Autowired
private SysUserMapper sysUserMapper;
/**
* 设置凭证匹配器匹配规定
*/
@Override
public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
// 创立凭证匹配器对象
HashedCredentialsMatcher hcm = new HashedCredentialsMatcher();
// 设置加密算法,与用户明码加密算法放弃始终
hcm.setHashAlgorithmName("MD5");
// 设置加密次数
hcm.setHashIterations(1);
super.setCredentialsMatcher(hcm);
}
/**
* 受权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
}
/**
* 重写认证 token 是从客户端传来的用户的账号信息
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 1. 获取用户输出的用户名
UsernamePasswordToken UToken = (UsernamePasswordToken) token;
String username = UToken.getUsername();
// 2. 基于用户名查用户信息
SysUser user = sysUserMapper.findUserByUsername(username);
// 3. 判断用户是否存在、是否禁用
if (user == null) {throw new UnknownAccountException();
}
if (user.getValid() == 0) {throw new LockedAccountException();
}
// 4. 封装用户信息
// 盐值是 ByteSource 格局的所以要转换
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());
System.out.println(user.getPassword());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, // principal ( 身份)
user.getPassword(), // hashedCredentials
credentialsSalt, // credentialsSalt
getName());// realName
return info;
}
}
- 3.3 controller 层
@RequestMapping("doLogin")
public JsonResult doLogin(String username,String password) {
// 每个用户都是一个 subject 对象
Subject subject = SecurityUtils.getSubject();
// 对用户进行封装
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
// token 被传给 securityManager;securityManager 在传递给 Authentication;Authentication 再传给 realm,从数据库中获取并封装用户信息
subject.login(token);
return new JsonResult("OK");
}
至此,借助 Shiro 实现了用户的登陆认证性能。