什么是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内置过滤器实现拦截 MapfilterMap=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; } }