Shiro原理流程,代码示例

Shiro组成流程图解

功能介绍:
主要实现用户身份认证,权限授权、加密、会话管理。
组成:
在这里插入图片描述
解释:

  1. Subject(主体):与软件交互的一个特定的实体(用户、第三方服务等)。
  2. SecurityManager(安全管理器) :Shiro 的核心,用来协调管理组件工作。
  3. Authenticator(认证管理器):负责执行认证操作。
  4. Authorizer(授权管理器):负责授权检测。
  5. SessionManager(会话管理):负责创建并管理用户 Session 生命周期,提供一
    个强有力的 Session 体验。
  6. SessionDAO:代表 SessionManager 执行 Session 持久(CRUD)动作,它允
    许任何存储的数据挂接到 session 管理基础上。
  7. CacheManager(缓存管理器):提供创建缓存实例和管理缓存生命周期的功能,对Session和授权数据进行缓存。
  8. Cryptography(加密管理器):提供了加密方式的设计及管理。
  9. 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")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的Apache Shiro代码示例,包括如何创建Shiro安全管理器,如何配置Shiro的认证和授权策略,以及如何使用Shiro进行认证和授权。 1. 创建Shiro安全管理器 ```java DefaultSecurityManager securityManager = new DefaultSecurityManager(); ``` 2. 配置Shiro的认证和授权策略 ```java // 配置认证策略 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher("SHA-256"); credentialsMatcher.setHashIterations(2); MyRealm realm = new MyRealm(); realm.setCredentialsMatcher(credentialsMatcher); securityManager.setRealm(realm); // 配置授权策略 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addRole("admin"); authorizationInfo.addStringPermission("user:create"); authorizationInfo.addStringPermission("user:update"); authorizationInfo.addStringPermission("user:delete"); securityManager.setAuthorizationInfo(authorizationInfo); ``` 3. 实现Shiro的Realm接口 ```java public class MyRealm extends AuthorizingRealm { // 实现认证方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); String password = getPasswordByUsername(username); if (password == null) { throw new UnknownAccountException("用户名不存在!"); } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, getName()); return authenticationInfo; } // 实现授权方法 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.setRoles(getRolesByUsername(username)); authorizationInfo.setStringPermissions(getPermissionsByUsername(username)); return authorizationInfo; } // 模拟数据库查询用户密码 private String getPasswordByUsername(String username) { return "123456"; } // 模拟数据库查询用户角色 private Set<String> getRolesByUsername(String username) { Set<String> roles = new HashSet<>(); roles.add("admin"); return roles; } // 模拟数据库查询用户权限 private Set<String> getPermissionsByUsername(String username) { Set<String> permissions = new HashSet<>(); permissions.add("user:create"); permissions.add("user:update"); permissions.add("user:delete"); return permissions; } } ``` 4. 使用Shiro进行认证和授权 ```java // 创建Subject对象 Subject subject = SecurityUtils.getSubject(); // 创建认证Token UsernamePasswordToken token = new UsernamePasswordToken("admin", "123456"); // 进行认证 subject.login(token); // 进行授权 boolean hasRole = subject.hasRole("admin"); boolean hasPermission = subject.isPermitted("user:create"); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可——叹——落叶飘零

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值