Shiro基础应用

1、Shiro简介:Shiro基础应用_第1张图片

2、首先从外部来看Shiro、即从应用程序角度来观察如何使用Shiro来完成工作。
Shiro基础应用_第2张图片
可以看到:引用代码直接交互的对象时Subject,也就是说Shiro的对外API核心就是Subject;其每个API的含义:
①:Subject:主体,代表着当前的用户,也就是与当前应用交互的东西,这是一个抽象的概念;所有的Subject都绑定到SecurityManager,与Subject所有的交互都会委托给SecurityManager。
②:SecurityManager:相当于Springmvc中的DispatcherServlet;是Shiro中的核心,所有的具体的交互都通过SecurityManager进行控制,管理所有的Subject,负责进行认证和授权、以及会话、缓存的管理。
③:Realm:可以有一个或多个Realm,可以认为是安全实体数据源,即用于获取安全实体的。

3、身份验证:
Shiro基础应用_第3张图片

@RequestMapping(value="/shiroLogin", method=RequestMethod.POST)
    public String login(@RequestParam("username") String username,
            @RequestParam("password") String password){
        // 获取 Subject 对象. Subject 即为当前用户. 调用 SecurityUtils.getSubject(); 进行获取. 
        Subject currentUser = SecurityUtils.getSubject();

     // 测试当前 Subject 是否已经被认证. 即是否已经登录. 调用 Subject 的 isAuthenticated() 方法. 
        if (!currentUser.isAuthenticated()) {
            // 把用户名和密码封装为一个 UsernamePasswordToken 对象. 
            // 直接调换用 UsernamePasswordToken 的构造器即可. 
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            token.setRememberMe(true);
            try {
                // 执行登陆操作. 
                // 调用 Subject 的 login(AuthenticationToken) 方法
                // 这说明 UsernamePasswordToken 是 AuthenticationToken 的实现类或子类
                currentUser.login(token);
            } 
            // ... catch more exceptions here (maybe custom ones specific to your application?
            // 认证异常的父类. 以上的异常都是该异常的子类. 
            catch (AuthenticationException ae) {
                System.out.println("登录失败: " + ae.getMessage());
                return "redirect:/login.jsp";
            }
        }
        return "redirect:/success.jsp";
    }
具体流程:
①:首先调用Subject.login(token)进行登录,他会自动委托给SecurityManager。
②:SecurityManager负责真正的身份验证逻辑,让Authenticator进行身份验证。
③:Authenticator真正的身份验证、这里可以自定义插入自己的实现。
④:Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证。
⑤:Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。

4、Realm:
我们自定义Realm一般继承 AuthorizingRealm (授权)即可; 其继承了 AuthenticatingRealm (即身份验证) ,而且也间接继承了 CachingRealm(带有缓存实现)。
Authenticator的职责是验证用户密码,是ShiroAPI中身份验证核心的入口点:

public AuthenticationInfo authenticate(AuthenticationToken authenticationToken)
throws AuthenticationException;

如果验证成功,则返回AuthenticationInfo验证信息,此信息包含身份以及凭证;如果验证失败,将抛出AuthenticationException的实现。SecurityManager接口继承了 Authenticator,另外还有一个modualModularRealmAuthenticator 实现,其委托给多个 Realm 进行验证,验证规则通过 AuthenticationStrategy 接口指定,默认提供的策略:AtLeastOneSuccessfulStrategy。

5、授权:授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作
等) 。 在授权中需了解的几个关键对象: 主体 (Subject) 、 资源 (Resource) 、 权限(Permission) 、角色(Role)。
①:Subject:即访问应用的用户。
②:Resource:在应用中用户可以访问的任何东西,用户只有授权之后才能访问。
③:Permission:安全策略中的原子授权单位,通过权限我们可以确定一个用户有没有访问对应的资源的权利。所以我们需要给用户赋予一定的权限,来确定这个用户什么资源可以访问。
④:Role:可以理解为权限集合,一般情况下我们会对一个用户赋予角色,不会直接赋予权限,这样对权限的操作比较方便,一般来讲,不同的位置不同角色应该有不同的权限。

6、授权的方式:Shiro中有三种授权的方式:
①:编程式:通过写 if/else 授权代码块完成:
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有权限
} else {
//无权限
}

②:注解式:通过在执行的 Java 方法上放置相应的注解完成:
@RequiresRoles("admin")
public void hello() {
//有权限
}
//没有权限则报错

③:JSP标签:在 JSP页面通过相应的标签完成:




我们在自定义Realm类中可以给用户赋予权限。

// 授权时 shiro 会回调的方法. 
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("1");
        //1、从PrincipalCollection中获取的登录的信息
        //即创建SimpleAuthentication对象得到pricipal
        Object principal = principals.getPrimaryPrincipal();

        //2、pricipal中已经包含了对应的权限信息
        //如果没有,则根据pricipal查询数据库
        Set roles = new HashSet<>();
        roles.add("user");

        if("admin".equals(principal)){
            roles.add("admin");
        }

        //3. 把权限信息封装为 SimpleAuthorizationInfo 对象并返回
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);

        return info;
    }

你可能感兴趣的:(Shiro)