shiro框架学习

1.登录

// 1 从Shiro框架中,获取一个Subject对象,代表当前会话的用户比如(com.shkj.financial.service.shiro.realm.ShiroAuthorizingRealm_0)
Subject subject = SecurityUtils.getSubject();
// 2 认证subject的身份
// 2.1 封装要认证的身份信息(用前端传来的用户名和密码封装成AuthenticationToken,在下面会说为什么) 
AuthenticationToken token = new UsernamePasswordToken(account.getUsername(), 
EncryptUtil.getMD5Str(account.getPassword()));
// 2.2 认证:当前会话对象调用login方法
subject.login(token);

调用subject.login(token);最后会进入AuthorizingRealm 的doGetAuthenticationInfo方法中进行登录认证,在上面的token中封装的username就在下面用到了。

@Component("shiroRealm")
public class ShiroAuthorizingRealm extends AuthorizingRealm {
    //注入自己的service层
    @Autowired
    private IUserService userService;
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //从authenticationToken也就是登录用UsernamePasswordToken封装的token中拿出
        //前端传来的用户名 可以点authenticationToken进入UsernamePasswordToken源码中了解为什么可以拿到
        String username = authenticationToken.getPrincipal().toString();
        //根据用户名查询该用户的信息
        AuthSysUser user = this.userService.findByUserName(username);
        // 用AuthenticationInfo对象,封装username和password
        ShiroUser shiroUser = new ShiroUser();
        String password = user.getUrPassword();
        shiroUser.setId(user.getUrId());
        shiroUser.setUserName(user.getUrUserName());
        shiroUser.setAuthCacheKey(user.getUrUserName() + user.getUrId());
        shiroUser.setPassword(password);
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(shiroUser, password, this.getName());
       //return时会触发密码验证
        return info;       
    }
}

想了解密码是何时怎样校验的可以看这位博主shiro密码校验

在登录校验成功之后会进行获取身份信息

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) 
      {
        //授权资源检查
        // 获取主身份
        String username = principalCollection.getPrimaryPrincipal().toString();
        ShiroUser shiroUser = (ShiroUser) principalCollection.getPrimaryPrincipal();
        //获取数据库中的用户角色对应的权限
        String username = shiroUser.getUserName();
        List<String> permissionList = this.userService.getUserPermssions(username);
        //创建授权对象
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //将当前用户权限设置给授权对象  permissionList放置的是order/create/*
        simpleAuthorizationInfo.addStringPermissions(permissionList);
        return simpleAuthorizationInfo;
    }

细粒度权限控制

         注解式的权限控制需要配置两个Bean,第一个是AdvisorAutoProxyCreator,代理生成器,需要借助SpringAOP来扫描@RequiresRoles和@RequiresPermissions等注解,生成代理类实现功能增强,从而实现权限控制。需要配合AuthorizationAttributeSourceAdvisor一起使用,否则权限注解无效,配置的DefaultAdvisorAutoProxyCreator相当于一个切面,下面这个类就相当于切点了,两个一起才能实现注解权限控制

   @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
@Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        autoProxyCreator.setProxyTargetClass(true);
        return autoProxyCreator;
    }

权限注解 

@RequiresAuthentication

表示当前 Subject 已经通过 login 进行了身份验证;即 Subject.isAuthenticated() 返回 true。

@RequiresUser

表示当前 Subject 已经身份验证或者通过记住我登录的。

@RequiresGuest

表示当前 Subject 没有身份验证或通过记住我登录过,即是游客身份。

@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND) logical是枚举类 有and和or

表示当前 Subject 需要角色 admin 和 user。

@RequiresPermissions (value={"sys:user:list", "sys:role:list"}, logical= Logical.OR)

表示当前 Subject 需要权限 sys:user:list或 sys:role:list(资源访问权限可以和后端访问路径完美匹配)可以将用户权限做缓存。

数据库表设计

为了简单化前后端的细粒度的权限控制将权限表和资源表进行合并 将权限直接定义为sys:user:list类型

  基于源码的登录流程在shiro框架中获取到subject对象后调用subject的login方法需要传入AuthenticationToken,UsernamePasswordToken实现了AuthenticationToken,调用UsernamePasswordToken的构造方法传入账号和加密后的密码,DelegatingSubject实现了Subject

实现了login方法调用securityManager中的login方法,最后在AbstractAuthenticator的authenticate

方法,然后调用ModularRealmAuthenticator的doAuthenticate,会根据你AuthenticatingRealm的Realms的数量判断是简单登录还是复杂登录,AuthorizingRealm(授权) AuthenticatingRealm(认证)

AuthorizingRealm extends AuthenticatingRealm 所以我们自定义实现AuthorizingRealm中的doGetAuthorizationInfo(授权)和doGetAuthenticationInfo(认证) 就可以完成自己的认证和授权。

shiro中出现的问题

前后端分离后用shiro自定义的session,前端是获取不到的需要自定义DefaultWebSessionManager用其getSessionId方法将sessionid拿出来重写放到response请求头上。

方法一 自定义DefaultWebSessionManager解决

前端获取不到session

方法二 跨域方式解决问题

前后端分离项目,前端cookie获取不到的解决方案

跨域解决的两种方式

解决跨域的方式 和问题解决

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值