当前位置:   article > 正文

三分钟彻底弄明白shiro原理_shiro getsubject 原理

shiro getsubject 原理

目前越来越多的项目都用到了shiro框架,毕竟它简单、容易(呃呃~其实一点都不简单),花三分钟理解下面的三个概念,你就掌握了shiro百分之九十的核心。
一、Subject:主体,代表了当前 “用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 Subject,如网络爬虫,机器人等;即一个抽象概念;所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager;可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者;
e.g.

 Subject currentUser = SecurityUtils.getSubject();
        try {
            currentUser.login(new UsernamePasswordToken(username, password));
        } 
  • 1
  • 2
  • 3
  • 4

(username和password就是前端传过来的用户名和密码)
在你的controller代码中直接这样写,shiro就可以帮我们完成登录验证和授权了。
login方法的实现是这样的:

public void login(AuthenticationToken token) throws AuthenticationException {
        this.clearRunAsIdentitiesInternal();
        Subject subject = this.securityManager.login(this, token);
        ...... 
    }
  • 1
  • 2
  • 3
  • 4
  • 5

重点看这句话

  Subject subject = this.securityManager.login(this, token);
  • 1

什么是SecurityManager?往下看
二、SecurityManager:安全管理器;即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;
login方法最终会找到我们自己实现的Realm类:
(通过ModularRealmAuthenticator 类的doAuthenticate 方法)

  protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
        this.assertRealmsConfigured();
        Collection<Realm> realms = this.getRealms();
        return realms.size() == 1 ? this.doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken) : this.doMultiRealmAuthentication(realms, authenticationToken);
    }
  • 1
  • 2
  • 3
  • 4
  • 5

到这,SecurityManager就把Subject和Realm串联起来了。
实际上是通过Authenticator 完成身份认证,而SecurityManager继承自
Authenticator ,ModularRealmAuthenticator 是其默认实现之一,它委托多个Realm验证,通过验证规则通过 AuthenticationStrategy 接口指定。这个接口又有多个实现。ModularRealmAuthenticator 默认使用 AtLeastOneSuccessfulStrategy 策略。

三、Realm:域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。

public class MyAuthorizingRealm extends AuthorizingRealm {

 

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        if (principals == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        }

        MyAccount = (MyAccount) getAvailablePrincipal(principals);
        Integer[] roleIds = admin.getRoleIds();
        Set<String> roles = roleService.queryByIds(roleIds);
        Set<String> permissions = permissionService.queryByRoleIds(roleIds);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setRoles(roles);
        info.setStringPermissions(permissions);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        String password = new String(upToken.getPassword());

        if (StringUtils.isEmpty(username)) {
            throw new AccountException("用户名不能为空");
        }
        if (StringUtils.isEmpty(password)) {
            throw new AccountException("密码不能为空");
        }

        List<MyAccount> adminList = adminService.findAdmin(username);
 
        if (adminList.size() == 0) {
            throw new UnknownAccountException("找不到用户(" + username + ")的帐号信息");
        }
        MyAccount = adminList.get(0);

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(password, admin.getPassword())) {
            throw new UnknownAccountException("找不到用户(" + username + ")的帐号信息");
        }

        return new SimpleAuthenticationInfo(admin, password, getName());
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

结束

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/533999
推荐阅读
  

闽ICP备14008679号