Shiro应用(一)--- 单独使用
程序员文章站
2022-07-12 15:53:19
...
shiro单独使用demo:
需要的依赖:
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!-- shiro的核心包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
shiro-permissions.ini文件(ini相对于properties文件的区别在于ini文件可以分组):
# -----------------------------------------------------------------------------
# 指定用户名以及角色(可选)
# username = password, role1, role2, ..., roleN
# -----------------------------------------------------------------------------
[users]
hurricane = 123, admin,handsome
# -----------------------------------------------------------------------------
# 指定角色与权限的对应关系
# roleName = perm1, perm2, ..., permN
# -----------------------------------------------------------------------------
[roles]
admin = user:add,user:delete
handsome = user:update
简单的日志输出配置log4j.properties:
log4j.rootLogger=info, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
log4j.logger.com.hurricane = info
主要测试代码:
package com.hurricane.learn.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
public class App {
public static void main(String[] args) {
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-permissions.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
AuthenticationToken token = new UsernamePasswordToken("hurricane", "123");
try {
subject.login(token);
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
} catch (IncorrectCredentialsException e) {
System.out.println("密码错误");
} catch (Exception e) {
System.out.println("未知错误");
}
System.out.println("用户登录成功:" + subject.isAuthenticated());
System.out.println("用户拥有admin角色:" + subject.hasRole("admin"));
System.out.println("用户拥有user:delete权限:" + subject.isPermitted("user:delete"));
System.out.println("用户拥有user:query权限:" + subject.isPermitted("user:query"));
}
}
以上即可实现shiro最基本的使用。
除此之外,shiro单独使用通常需要使用自定义的realm进行校验授权,以及对用户密码进行散列编码。
自定义realm:
shiro-permissions.ini中加入:
[main]
customRealm = com.hurricane.learn.shiro.util.CustomRealm
securityManager.realms = $customRealm
CustomRealm的代码为:
package com.hurricane.learn.shiro.util;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
public class CustomRealm extends AuthorizingRealm{
/**
* 授权
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//primaryPrincipal是认证阶段传入的principal
Object primaryPrincipal = principals.getPrimaryPrincipal();
//根据primaryPrincipal从数据库中查询对应的角色与权限,并封装进要返回的AuthorizationInfo
info.addRole("role1");
info.addStringPermission("user:create");
return info;
}
/**
* 认证
* 返回null代表用户名不存在
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
if (token.getPrincipal()==null || token.getPrincipal().toString().equals("")) {
return null;
}
//判断用户名是否存在,若不存在,返回null
// ...
String dbPassword = "123";
//将从数据库中获取的密码传入,shiro会进行校验,此处传入的principal应为工程中对用户信息进行封装的类的实例,此处简写为一个用户名的字符串
AuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(),dbPassword,"realm1");
return info;
}
}
以上就可以使shiro的校验走自定义的realm。
对密码进行加盐与散列:
shiro-permissions.ini中关于自定义域的声明中指定散列的算法与散列的次数:
[main]
credentialsMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName = md5
credentialsMatcher.hashIterations = 2
customRealm = com.hurricane.learn.shiro.util.CustomRealm
customRealm.credentialsMatcher = $credentialsMatcher
securityManager.realms = $customRealm
在进行认证的方法中传入盐与加密后的密码(一般为从数据库中读取的结果),如下:
/**
* 认证
* 返回null代表用户名不存在
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
if (token.getPrincipal()==null || token.getPrincipal().toString().equals("")) {
return null;
}
//判断用户名是否存在,若不存在,返回null
// ...
//755ac1a684638060155ccc37625b954b是123加盐sss并进行2次md5散列后的结果
String dbPassword = "755ac1a684638060155ccc37625b954b";
//将从数据库中获取的密码传入,shiro会进行校验,此处传入的principal应为工程中对用户信息进行封装的类的实例,此处简写为一个用户名的字符串
AuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(),dbPassword,ByteSource.Util.bytes("sss"),"realm1");
return info;
}
参考:
燕青的****
上一篇: TypeScript(数据类型、函数、类、接口、泛型)
下一篇: JSONConfig处理日期