什么是Shiro
Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
Shiro的主要应用有认证、授权、安全数据加密、会话管理、系统集成(与web集成)、与Spring和SpringBoot框架缓存框架等集成
Shiro的特点
简单、灵活
可脱离spring
粒度较粗,可根据需要再自行扩展
Shiro整体架构
Authenticator :认证器,管理登录登出
Authorizer:授权器,权限控制
SessionManager:shiro的session管理机制,可脱离web容器使用session,session的增删改查
SessionDAO:
Cache Manager: 缓存管理器,缓存角色和权限数据
Pluggable Realms: shiro和数据库的桥梁
Cryptography:数据加密
Shiro认证的过程:
创建SecurityManager对象后: 主体提交认证请求——》SecurityManager获取认证请求——》Authenticator认证请求——》Realm提供验证数据
与SpringBoot的集成
shiro配置,注入bean
/**
* @author : Jack Wu
* @Title: ShiroConfig
* @ProjectName boot-shiro
* @Description: TODO
* @date 2019/3/6 20:05
*/
@Configuration
public class ShiroConfig {
//创建ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//添加shiro内置过滤器实现拦截
Map<String,String> filterMap=new LinkedHashMap<>();
filterMap.put("/add","authc");
filterMap.put("/update","authc");
filterMap.put("/login","anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
shiroFilterFactoryBean.setLoginUrl("/login");
return shiroFilterFactoryBean;
}
//创建DefaultWebSecurityManager
@Bean(name = "defaultWebSecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("customRealm") CustomRealm customRealm){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
//关联Realm 并加密
HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("md5");
matcher.setHashIterations(1);
customRealm.setCredentialsMatcher(matcher);
securityManager.setRealm(customRealm);
return securityManager;
}
//创建自定义Realm对象,
@Bean(name = "customRealm")
public CustomRealm getRealm(){
return new CustomRealm();
}
}
实现校验逻辑
/**
* @author : Jack Wu
* @Description: TODO
* @date 2019/3/6 19:47
*/
@RequestMapping(value = "/sulogin",method = RequestMethod.POST)
public String getLogin(String name, String password, Model model){
Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(name,password);
try {
subject.login(token);
return "add";
} catch (UnknownAccountException e) {
e.printStackTrace();
model.addAttribute("loginMessage","用户名不存在");
return "login";
}catch (IncorrectCredentialsException e){
e.printStackTrace();
model.addAttribute("loginMessage","密码错误");
return "login";
}
}
其中自定义的Realm如下
/**
* @author : Jack Wu
* @Title: CustomRealm
* @ProjectName boot-shiro
* @Description: TODO
* @date 2019/3/6 20:09
*/
public class CustomRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证用户
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username= (String) authenticationToken.getPrincipal();
String password=getPassWordByName(username);
SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo("admin",password,"customRealm");
authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(getSalt()));
return authenticationInfo;
}
}