shiro--自定义Realm接口
Realm接口

在实际项目中,我们不会直接实现Realm接口,而是直接继承AuthorizingRealm,实现认证和授权功能。它需要强制重写两个方法(doGetAuthorizationInfo和doGetAuthenticationInfo)。
自定义realm,从数据库获取密码
shiro.ini
#声明自定义的realm,且为安全管理器指定realm
[main]
definitionRealm=demo.realm.DefinitionRealm
securityManager.realms=$definitionRealm
pom.xml
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 这里有用到日志打印,所以引入 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
demo类
package demo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ShiroDemo {
public static void main(String[] args) {
//1.导入权限ini文件,创建SecurityManagerFactory
IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//2.获取SecurityManager,绑定到SecurityUtils中
SecurityManager securityManager =factory.getInstance();
SecurityUtils.setSecurityManager( securityManager);
//3.获取一个用户主体
Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("guest", "123");
currentUser.login(token);
System.out.println("是否登录成功:"+currentUser.isAuthenticated());
}
}
自定义realm类
package demo.realm;
import demo.service.SecurityService;
import demo.service.impl.SecurityServiceImpl;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
public class DefinitionRealm extends AuthorizingRealm {
/***
* 鉴权方法
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
/***
* 认证方法
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取登录名
String username = (String) authenticationToken.getPrincipal();
SecurityService service = new SecurityServiceImpl();
String password = service.findPasswordByUsername(username);
if("".equals(password)){
throw new UnknownAccountException("密码不存在!");
}
return new SimpleAuthenticationInfo(username, password, getName());
}
}
编码解码工具类
package tools;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.codec.Hex;
// 编码工具类
public class EncodesUtil {
/***
* Hex 数组转String
* @param input
* @return
*/
public static String encodeHex(byte[] input) {
return Hex.encodeToString(input);
}
/***
* Hex string 转数组
* @param input
* @return
*/
public static byte[] decodeHex(String input) {
return Hex.decode(input);
}
/**
* base64 数组转字符串
* @param input
* @return
*/
public static String encodeBase64(byte[] input) {
return Base64.encodeToString(input);
}
/***
* base64 字符串转数组
* @param input
* @return
*/
public static byte[] decodeBase64(String input) {
return Base64.decode(input);
}
}
生成摘要工具类
package tools;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import java.util.HashMap;
import java.util.Map;
// 生成摘要
public class DigestsUtil {
private static final String SHA1 = "SHA-1";
private static final Integer ITERATIONS = 512;
/***
* SHA1摘要算法
* @param input 明文字符串
* @param salt 干扰数据
* @return
*/
public static String sha1(String input, String salt) {
return new SimpleHash(SHA1,input,salt,ITERATIONS).toString();
}
/**
* 随机生成salt
* @return
*/
public static String generateSalt() {
SecureRandomNumberGenerator secureRandomNumberGenerator = new SecureRandomNumberGenerator();
return secureRandomNumberGenerator.nextBytes().toHex();
}
/**
* 生成密码和salt的密文
* @param passwordPlan
* @return
*/
public static Map<String,String> entryptPassword(String passwordPlan){
Map<String,String> map = new HashMap<>();
String salt = generateSalt();
String password = sha1(passwordPlan,salt);
map.put("password",password);
map.put("salt",salt);
return map;
}
}
自定义Realm类2
package realm;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import service.SecurityService;
import service.impl.SecurityServiceImpl;
import tools.DigestsUtil;
import java.util.Map;
public class DefinitionRealm extends AuthorizingRealm {
// 在构造函数中修改密码比较器
public DefinitionRealm(){
// 指定密码匹配方式sha1
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);
// 指定密码迭代次数
matcher.setHashIterations(DigestsUtil.ITERATIONS);
// 使用父层方法是匹配方式生效
setCredentialsMatcher(matcher);
}
/***
* 鉴权方法
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
/***
* 认证方法
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取登录名
String username = (String) authenticationToken.getPrincipal();
SecurityService service = new SecurityServiceImpl();
// 获取数据库密码和salt
Map<String,String> map = service.findPasswordByUsername(username);
if(map.isEmpty()){
throw new UnknownAccountException("账号不存在!");
}
String password = map.get("password");
String salt = map.get("salt");
return new SimpleAuthenticationInfo(username, password, ByteSource.Util.bytes(salt), getName());
}
}
SecurityService和SecurityServiceImpl
package service;
import java.util.Map;
// 模拟数据库操作
public interface SecurityService {
Map<String,String> findPasswordByUsername(String username);
}
package service.impl;
import service.SecurityService;
import tools.DigestsUtil;
import java.util.Map;
public class SecurityServiceImpl implements SecurityService {
@Override
public Map<String,String> findPasswordByUsername(String username) {
return DigestsUtil.entryptPassword("123");
}
}
本文来自博客园,作者:NE_STOP,转载请注明原文链接:https://www.cnblogs.com/alineverstop/p/19453906
浙公网安备 33010602011771号