Shiro原理流程,代码示例
Posted 宇宙磅礴而冷漠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shiro原理流程,代码示例相关的知识,希望对你有一定的参考价值。
Shiro组成流程图解
功能介绍:
主要实现用户身份认证,权限授权、加密、会话管理。
组成:
解释:
- Subject(主体):与软件交互的一个特定的实体(用户、第三方服务等)。
- SecurityManager(安全管理器) :Shiro 的核心,用来协调管理组件工作。
- Authenticator(认证管理器):负责执行认证操作。
- Authorizer(授权管理器):负责授权检测。
- SessionManager(会话管理):负责创建并管理用户 Session 生命周期,提供一
个强有力的 Session 体验。 - SessionDAO:代表 SessionManager 执行 Session 持久(CRUD)动作,它允
许任何存储的数据挂接到 session 管理基础上。 - CacheManager(缓存管理器):提供创建缓存实例和管理缓存生命周期的功能,对Session和授权数据进行缓存。
- Cryptography(加密管理器):提供了加密方式的设计及管理。
- Realms(领域对象):是 shiro 和你的应用程序安全数据之间的桥梁,Realm存储授权和认证的逻辑。
主要工作流程:
代码示例
依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
核心配置
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
@Configuration
public class SpringShiroConfig {
@Bean
public SecurityManager securityManager(Realm realm,CacheManager cacheManager,RememberMeManager rememberMeManager,SessionManager sessionManager){
//web应用中,这个接口的具体实现建议DefaultWebSecurityManager
//DefaultSecurityManager不一样
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
securityManager.setRealm(realm);
securityManager.setCacheManager(cacheManager);
securityManager.setRememberMeManager(rememberMeManager);
securityManager.setSessionManager(sessionManager);
return securityManager;
}
//配置认证过滤规则,哪些资源需要认证访问,哪些资源可以匿名访问
//规则我们来定义,规则的检验是在shiro框架中借助大量过滤器(Filter)去实现。
//shiro提供了过滤类型,但是基于类型创建其实例需要通过过滤器工厂
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean filterFactoryBean=new ShiroFilterFactoryBean();
LinkedHashMap<String,String> map=new LinkedHashMap<>();
//存储规则key为资源名,value为规则
map.put("/bower_components/**","anno" );//anno为匿名访问,shiro定义字符串
map.put("/build/**","anno" );
map.put("/dist/**","anno" );
map.put("/plugins/**","anno" );
map.put("/user/doLogin","anno" );
map.put("/doLogout","logout" );//退出时会自动回到登陆界面
//除了以上资源,后续所有资源都要认证访问
map.put("/**","authc" );//authc表示需要认证
//map.put("/**","user" );//表示可以从客户端获取信息
//如何判定访问这个资源时是否已经认证过了呢?
filterFactoryBean.setSecurityManager(securityManager);
//假如访问时还没有通过认证?跳转到指定认证页面
filterFactoryBean.setLoginUrl("/doLoginUI");
filterFactoryBean.setFilterChainDefinitionMap(map);
return filterFactoryBean;
}
//顾问对象
//负责找到类中使用此注解@RequiresPermissions描述的方法,
//这些方法为授权访问切入点方法,当执行这些方法时会由通知(Advice)对象
//调用一个对象(securityManager)完成权限检测及授权
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor a=new AuthorizationAttributeSourceAdvisor();
a.setSecurityManager(securityManager);
return a;
}
@Bean
//缓存管理器,频繁访问数据库
public CacheManager shirocachemanager(){
return new MemoryConstrainedCacheManager();
}
public RememberMeManager rememberMeManager(){
CookieRememberMeManager rememberMeManager=
new CookieRememberMeManager();
SimpleCookie cookie=new SimpleCookie("rememberMe");
cookie.setMaxAge(7*24*60*60);
rememberMeManager.setCookie(cookie);
return rememberMeManager;
}
public SessionManager sessionManager(){
DefaultWebSessionManager sessionManager=
new DefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(1800000L*2);//1 hour
//服务器重启丢掉用户cookie
sessionManager.setSessionIdUrlRewritingEnabled(false);//不想要用false
return sessionManager;
}
}
认证授权
import org.apache.shiro.authc.*;
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 java.util.HashSet;
import java.util.Set;
@Service
public class ShiroUserRealm extends AuthorizingRealm {
//继承AuthorizingRealm授权和认证
//继承AuthenticatingRealm(只认证)
//Realm可获取认证数据信息和授权数据信息
@Autowired
private SysUserDao sysUserDao;//自定义的接口
@Override
//用于获取用户的权限信息并封装
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登陆用户
SysUser user=(SysUser)principalCollection.getPrimaryPrincipal();
//获取登陆用户的角色权限数据
List<String> perssion=sysMenuDao.findPermisisin(user.getId());
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
Set<String> setPerssion=new HashSet<>();
for(String per:perssion){
if(!StringUtils.isEmpty(per)){
set.add(per);
}
}
info.setStringPermissions(setPerssion);
//封装数据并返回,交给securityManager
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取登陆时输入的用户名
UsernamePasswordToken upt=(UsernamePasswordToken)authenticationToken;
String username=upt.getUsername();
//基于用户名查找数据库信息
SysUser sysUser=sysUserDao.findUserByUsername(username);
//校验用户是否已被禁用
if(sysUser==null){
throw new UnknownAccountException();
}
if(sysUser.getValid()==0){
throw new LockedAccountException();
}
//封装用户信息,交给securityManager进行认证
ByteSource credentialsSalt=ByteSource.Util.bytes(sysUser.getSalt());
SimpleAuthenticationInfo info=
new SimpleAuthenticationInfo(sysUser,
sysUser.getPassword(),
credentialsSalt,getName());
return info;
}
//get和set选一个就行
//@Override
//public CredentialsMatcher getCredentialsMatcher() {
// HashedCredentialsMatcher credentialsMatcher=new HashedCredentialsMatcher("MD5");
//credentialsMatcher.setHashIterations(1);
//return credentialsMatcher;
//}
@Override
public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
//构建凭证匹配对象
HashedCredentialsMatcher cMatcher=new HashedCredentialsMatcher();
//设置加密算法
cMatcher.setHashAlgorithmName("MD5");
//设置加密次数
cMatcher.setHashIterations(1);
super.setCredentialsMatcher(cMatcher);
}
}
用户登录记录令牌
//controller层
public JsonResult doLogin(String name,String password){
//获取用户名,aop里记录日志可以用
//(SysUser)SecurityUtils.getSubject().getPrincipal();
UsernamePasswordToken token = new UsernamePasswordToken(name,password);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
return new JsonResult("login ok");
}
service层标识权限
//授权访问切入点方法,标识在service层的类或方法上
@RequiresPermissions(value = "sys:user:update")
以上是关于Shiro原理流程,代码示例的主要内容,如果未能解决你的问题,请参考以下文章
全栈编程系列SpringBoot整合Shiro(含KickoutSessionControlFilter并发在线人数控制以及不生效问题配置启动异常No SecurityManager...)(代码片段