Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shiro认证思路分析 #16

Open
NewBrandSTONE opened this issue Jan 3, 2019 · 1 comment
Open

Shiro认证思路分析 #16

NewBrandSTONE opened this issue Jan 3, 2019 · 1 comment
Labels
Shiro Shiro

Comments

@NewBrandSTONE
Copy link
Owner

NewBrandSTONE commented Jan 3, 2019

Shiro 的认证过程

  1. 新建 shiro-demo 工程

  2. 创建 shiro-test module

  3. 在 shiro-test 中引入相关依赖

    • junit
    • shiro-core
    • 最终 shiro-test 的 pom.xml 文件如下
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>shiro-demo</artifactId>
            <groupId>com.ozyoung.shiro</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>shiro-test</artifactId>
    
        <dependencies>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>RELEASE</version>
            </dependency>
        </dependencies>
    </project>

核心思想

  1. 构建 SecurityManager 环境
  2. 主体提交认证请求
    • Subject 提交认证请求道 Security Manager ,Security Manager 调用 Authenticor 来进行认证,Authenticor 调用 Realm 获取数据库中的数据,将 Subject 提交的数据和 Realms 从数据库中拿到的数据进行比较。

踩下的坑

  1. 运行以下代码报错 No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
    • 代码如下:
package com.young.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AuthenticationTest {

    private Logger logger = LoggerFactory.getLogger(getClass());
    private SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();

    @Before
    public void addUser() {
        simpleAccountRealm.addAccount("mike", "123456");
    }

    @Test
    public void testAuthentication() {

        // 1.构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();

        defaultSecurityManager.setRealm(simpleAccountRealm);

        // 2.主体提交认证
        Subject subject = SecurityUtils.getSubject();

        boolean isAuthenticated = subject.isAuthenticated();
        logger.info("主体认证-{}", isAuthenticated);

    }
}
  • 当前代码中没有可用的 SecurityManager,或者是 ThreadContext 是单例的,这是一个无效的应用程序配置。
  • 解决方法,使用 SecurityUtils.setSecurityManager(defaultSecurityManager) 方法,给当前代码设置 SecurityManager。
package com.young.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;

public class AuthenticationTest {

    private SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();

    @Before
    public void addUser() {
        simpleAccountRealm.addAccount("mike", "123456");
    }

    @Test
    public void testAuthentication() {

        // 1.构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(simpleAccountRealm);

        // 2.设置SecurityManager
        SecurityUtils.setSecurityManager(defaultSecurityManager);

        // 2.主体提交认证
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("mike", "123456");

        subject.login(usernamePasswordToken);

        boolean isAuthenticated = subject.isAuthenticated();

        System.out.println("主体认证-" + isAuthenticated);

    }
}

认证过程分析

  1. 使用 Subject.login(UsernamePasswordToken)

    • 调用 login 方法
    • 传入 UsernamePasswordToken 值
  2. 在 Subject.login(token) 的内部是通过调用 SecurityManager.login(delegateSubject, token)

  3. DefaultSercurityManager.login 方法调用 AuthenticatingSecurityManager.authenticate(token) 方法来实现

  4. authenticate 方法中,使用 authenticator.authenticate(token) 方法实现认证。

  5. authenticator 中调用 ModularRealmAuthenticator.doAuthenticate 方法实现认证

    • 其中获取了当前可用的 Realms,用来读取用户数据库或者传入的用户数据。
@NewBrandSTONE NewBrandSTONE added the Shiro Shiro label Jan 3, 2019
@NewBrandSTONE
Copy link
Owner Author

认证步骤

  1. 通过 SecurityUtils.getSubject(),获取当前访问系统的 Subject。
  2. 通过 Subject.isAuthenticated(),判断当前用户是否已经被认证,即是否已经登录。
  3. 若没有被认证,则把用户名和密码封装为 UsernamePasswordToken 对象。
    • 创建一个表单页面,用来提交用户名和密码
    • 把请求提交到 SpringMVC 的 Handler 上。
    • 获取用户名和密码。
  4. 调用执行登录的方法,Subject.login(token)。
  5. 自定义 Realm 的方法,从数据库中获取对应的记录,返回给 Shiro。
    • 实际上需要继承 org.apache.shiro.realm.AuthenticatingRealm 类
    • 实现 doGetAuthenticationInfo(AuthenticationToken)方法。
  6. 由 Shiro 完成对密码的比对。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Shiro Shiro
Projects
None yet
Development

No branches or pull requests

1 participant