Shiro(2)-身份认证

基本概念

身份验证
即在应用中谁能证明他就是他本人。一般提供如他们的身份ID 一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明。在 shiro 中,用户需要提供principals (身份)和credentials(证明)给shiro,从而应用能验证用户身份

principals
身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体可以有多个principals,但只有一个Primary principals,一般是用户名/密码/手机号。

证明/凭证
即只有主体知道的安全值,如密码/数字证书等。
最常见的principals和credentials组合就是用户名/密码了。

认证流程

在这里插入图片描述

用户登陆认证

导入jar包

<dependency>
	    <groupId>org.apache.shiro</groupId>
	    <artifactId>shiro-core</artifactId>
	    <version>1.3.2</version>
	</dependency>
	<!-- junit -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.9</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>commons-logging</groupId>
		<artifactId>commons-logging</artifactId>
		<version>1.2</version>
	</dependency>

配置shiro环境文件shiro.ini

[users]
root=123
 public static void main(String[] args) {
	//创建SecurityManager工厂,读取配置文件
	//注意导包
	Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
	//通过SecurityManager工厂获取SecurityManager实例
	SecurityManager securityManager = factory.getInstance();
	//将SecurityManager对象设置到环境中
	SecurityUtils.setSecurityManager(securityManager);
	//通过SecurityUtils获取主体Subject
	Subject subject = SecurityUtils.getSubject();
	//用户登陆的用户名和密码,而ini文件中的用户名和密码相当数据库中的user
	UsernamePasswordToken token = new UsernamePasswordToken("root", "123");
	try {
	    //进行用户身份验证,如果验证失败则抛出异常
	    subject.login(token);
	    //判断用户是否通过验证
	    if (subject.isAuthenticated()) {
		    System.out.println("登陆成功");
		}
	} catch (AuthenticationException e) {
	    e.printStackTrace();
	    System.out.println("用户登陆失败");
	}
    }

自定义Realm

Shiro默认使用自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm。

在这里插入图片描述
最基础的是Realm接口,CachingRealm负责缓存处理,AuthenticationRealm负责认证,AuthorizingRealm负责授权,通常自定义的realm继承AuthorizingRealm

自定义Realm实现

public class UserRealm extends AuthorizingRealm {
    
    public String getName(){
	return "userRealm";
    }
    
    
    /**
     * @Description:获取权限信息
     * @param principals
     * @return
     */
    protected AuthorizationInfo doGetAuthorizationInfo(
	    PrincipalCollection principals) {
	
	return null;
    }

    
    /**
     * @Description:完成身份认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    protected AuthenticationInfo doGetAuthenticationInfo(
	    AuthenticationToken token) throws AuthenticationException {
	//获取用户输入的用户名
	String username = (String) token.getPrincipal();
	System.out.println("第一个Realm:");
	System.out.println("username===="+username);
	//根据用户名查询数据库获取密码
	String password = "123";
	//将从数据库中获取的信息封装到
	SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,password,getName());
	return info;
    }
}

要想使用自定义的realm需要先在shiro.ini中配置Realm,类似于spring的依赖注入

[main]
#自定义 realm
userRealm=com.QEcode.realm.UserRealm
#将realm设置到securityManager
securityManager.realms=$userRealm

Authenticator

Authenticator 的职责是验证用户帐号,是 Shiro API 中身份验证核心的入口点.
在这里插入图片描述

如果验证成功,将返回 AuthenticationInfo 验证信息;此信息中包含了身份及凭证;如果验证失败将抛出相应的 AuthenticationException 实现。

SecurityManager 接口继承了 Authenticator,另外还有一个 ModularRealmAuthenticator 实现,其委托给多个 Realm 进行验证,验证规则通过 AuthenticationStrategy 接口指定,默认提供的实现:
FirstSuccessfulStrategy:只要有一个 Realm 验证成功即可,只返回第一个 Realm 身份验证成功的认证信息,其他的忽略;
AtLeastOneSuccessfulStrategy:只要有一个 Realm 验证成功即可,和 FirstSuccessfulStrategy不同,返回所有 Realm 身份验证成功的认证信息;
AllSuccessfulStrategy所有 Realm 验证成功才算成功,且返回所有 Realm 身份验证成功的认证信息,如果有一个失败就失败了。
ModularRealmAuthenticator 默认使AtLeastOneSuccessfulStrategy 策略。

在ini 配置文件中指定

[main]
userRealm = com.QEcode.realm.UserRealm
userRealm2 = com.QEcode.realm.UserRealm2

# 配置验证器
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
# 指定验证规则为AllSuccessfulStrategy 所有 Realm 验证成功才算成功,
allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy

# 指定验证规则为AtLeastOneSuccessfulStrategy 只要有一个 Realm 验证成功返回所有 Realm 身份验证成功的认证信息
atLeastOneSuccessfulStrategy = org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy

# 指定验证规则为FirstSuccessfulStrategy 只要有一个 Realm 验证成功即可,只返回第一个 Realm 身份验证成功的认证信息
firstSuccessfulStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy

#指定 securityManager 的 authenticator 实现
authenticator.authenticationStrategy=$firstSuccessfulStrategy

securityManager.authenticator=$authenticator

securityManager.realms=$userRealm , $userRealm2

public class UserRealm2 extends AuthorizingRealm {
    
    public String getName(){
	return "userRealm2";
    }
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
	    PrincipalCollection principals) {
	// TODO 自动生成的方法存根
	return null;
    }

    /**
     * @Description:身份认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
	    AuthenticationToken token) throws AuthenticationException {
	// 获取用户输入的用户名
	String username = (String) token.getPrincipal();
	System.out.println("第二个Realm:");
	System.out.println("username====" + username);
	// 根据用户名查询数据库获取密码
	String password = "123";
	// 将从数据库中获取的信息封装到
	SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,
		password, getName());
	return null;
    }
}

猜你喜欢

转载自blog.csdn.net/QEcode/article/details/83419833