学习了shiro分析下源码
从官网可以知道shiro的构成,核心:Subject,SecurityManager,Realm
Realm中的核心Authorization(用于做权限配置)和Authentication(用于做身份认证),两个单词很接近但意义不同
SecurityManager是核心用来管理个个组件
网上可以找一大堆配置shiro的文件这里就不贴了,来写一下整个过程是怎么进行的
首先是配置:
配置自定义Ream
public class MyShiroRealm extends AuthorizingRealm { @Resource private UserInfoService userInfoService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()"); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); UserInfo userInfo = (UserInfo)principals.getPrimaryPrincipal(); for(SysRole role:userInfo.getRoleList()){ authorizationInfo.addRole(role.getRole()); for(SysPermission p:role.getPermissions()){ authorizationInfo.addStringPermission(p.getPermission()); } } return authorizationInfo; } /*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("MyShiroRealm.doGetAuthenticationInfo()"); //获取用户的输入的账号. String username = (String)token.getPrincipal(); System.out.println(token.getCredentials()); //通过username从数据库中查找 User对象,如果找到,没找到. //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法 UserInfo userInfo = userInfoService.findByUsername(username); System.out.println("----->>userInfo="+userInfo); if(userInfo == null){ return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( userInfo, //用户名 userInfo.getPassword(), //密码 ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt getName() //realm name ); return authenticationInfo; } }
实现 AuthorizingRealm,实现权限配置和用户认证,注意下身份认证中 SimpleAuthenticationInfo 的四个参数
principal 和 realmName相当于创建了一个 SimplePrincipalCollection ,并在其中的 realmPrincipals中添加了key是realmName value是principal
hashedCredentials 是用来判断密码的正确性 , credentialsSalt是为了确保在密码一致的情况下还可以进行唯一性验证(比如admin和test的密码都是123,如何确定当前的密码123是admin还是test就是靠credentialsSalt)
我们再来看下继承类AuthorizingRealm 的配置
还可以进行配置credentialsMatcher(用于进行密码加密),authenticationCache(缓存)
credentialsMatcher是个借口看下他的实现
我们可以使用 HashedCredentialsMatcher
配置一个bean
配置到自定义realm里面
我们的自定义realm就完成了,然后把realm注册到SecurityManager,把SecurityManager注入到ShiroFilterFactoryBean,我们的shiro就配置完成了
@Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { System.out.println("ShiroConfiguration.shirFilter()"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //拦截器. Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>(); // 配置不会被拦截的链接 顺序判断 filterChainDefinitionMap.put("/static/**", "anon"); //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 filterChainDefinitionMap.put("/logout", "logout"); //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> filterChainDefinitionMap.put("/**", "authc"); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/login"); // 登录成功后要跳转的链接 shiroFilterFactoryBean.setSuccessUrl("/index"); Map<String, Filter> filters = new LinkedHashMap<>(); filters.put("authc",FormAuthenticationFilter()); //未授权界面; shiroFilterFactoryBean.setUnauthorizedUrl("/403"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); shiroFilterFactoryBean.setFilters(filters); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); return securityManager; }
转载于:https://www.cnblogs.com/lu-wei/p/8650677.html