<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.4.0version>
dependency>
shiro框架认为单纯的md5加密不是很安全,所以可以引入shiro的Md5Hash,即md5哈希散列
public static void main(String[] args) {
Md5Hash md5Hash = new Md5Hash();
//不要用set进行赋值,错误!!!!
md5Hash.setBytes("123".getBytes());
System.out.println(md5Hash.toHex());
//应该在构造方法中进行加密,正确!!!!
//此时就是默认的md5,并没有进行散列
Md5Hash md5Hash1 = new Md5Hash("123321");
System.out.println(md5Hash1.toHex());
//此时是加盐加hash散列的md5算法
Md5Hash md5Hash2 = new Md5Hash("123321", "pf@5", 1024);
System.out.println(md5Hash2.toHex());
}
在resource中创建shiro.ini文件(方便测试)
[users]
if=123321
随便创建一个HelloWorld.java文件,在main方法中写下
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
/**
* @Author if
* @Description: What is it
* @Date 2021-02-08 下午 03:27
*/
public class HelloWorld {
public static void main(String[] args) {
//1.创建安全管理器对象
DefaultSecurityManager securityManager=new DefaultSecurityManager();
//2.给安全管理器设置realm
securityManager.setRealm(new IniRealm("classpath:shiro.ini"));
//3.SecurityUtils给全局安全工具类设置安全管理器
SecurityUtils.setSecurityManager(securityManager);
//4.关键对象Subject主体
Subject subject=SecurityUtils.getSubject();
//5.创建令牌
UsernamePasswordToken token = new UsernamePasswordToken("if","123321");
try{
System.out.println("认证状态:"+(subject.isAuthenticated()?"认证成功":"还未认证"));
subject.login(token);
System.out.println("认证状态:"+(subject.isAuthenticated()?"认证成功":"还未认证"));
}catch(UnknownAccountException e){
System.out.println("用户名错误");
}catch (IncorrectCredentialsException e){
System.out.println("密码错误");
}
}
}
由于为了方便,使用了jdbc作为数据库连接
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;
import org.apache.shiro.util.ByteSource;
import java.sql.*;
/**
* @Author if
* @Description: 自定义realm实现,将认证/授权数据的来源转为数据库的实现
* @Date 2021-02-08 下午 10:53
*/
public class CustomerRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//身份信息(其实就是用户名等)
String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
System.out.println(primaryPrincipal+"访问了doGetAuthorizationInfo()方法");
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//其实这里应该是放数据库中对应的权限角色(一个账号可以有多个角色),懒得去新加字段然后连接了
simpleAuthorizationInfo.addRole("user");
simpleAuthorizationInfo.addRole("admin");
return simpleAuthorizationInfo;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取身份信息(手机号/邮箱等)
String username= (String) authenticationToken.getPrincipal();
//根据身份信息使用jdbc查询数据库
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql:///test1", "root", "数据库密码");
String sql = "select * from t_user where uname=?";
PreparedStatement ptmt = conn.prepareStatement(sql);
ptmt.setString(1,username);
ResultSet rs = ptmt.executeQuery();
//因为查询出来的头指针指向null,需要先next一下才能指向第一个结果
rs.next();
System.out.println("数据库中\n"+rs.getString("uname")+" ---- "+rs.getString("pwd"));
//进行判断
if(rs.getString("uname").equals(username)){
/**
* 传入3个参数
* 1.数据库中正确的用户名
* 2.数据库中正确的密码
* 3.(可选)若有加盐则填入盐(盐一般写入数据库中,每个用户都可以不同,ByteSource.Util.bytes("盐")即可 )
* 4.当前的realm信息(根据this.getName()获得)
*/
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(rs.getString("uname"),rs.getString("pwd"), ByteSource.Util.bytes(rs.getString("salt")),this.getName());
conn.close();
ptmt.close();
rs.close();
return simpleAuthenticationInfo;
}
} catch (Exception e) {
return null;
}
return null;
}
}
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @Author if
* @Description: 使用自定义realm实现 认证授权数据源于数据库
* @Date 2021-02-08 下午 10:58
*/
public class TestCustomerRealm {
public static void main(String[] args) {
//1.创建安全管理器对象
DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
//2.new自定义realm
CustomerRealm customerRealm = new CustomerRealm();
//3.设置加md5、加hash散列加密方式配置(加盐配置在CustomerRealm类中写)
HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
hashedCredentialsMatcher.setHashIterations(1024);
customerRealm.setCredentialsMatcher(hashedCredentialsMatcher);
//4.给安全管理器设置自定义的realm
defaultSecurityManager.setRealm(customerRealm);
//5.SecurityUtils给全局安全工具类设置安全管理器
SecurityUtils.setSecurityManager(defaultSecurityManager);
//6.关键对象Subject主体
Subject subject=SecurityUtils.getSubject();
//7.创建令牌
UsernamePasswordToken token = new UsernamePasswordToken("Tom","123321");
try{
System.out.println("认证状态:"+(subject.isAuthenticated()?"认证成功":"还未认证"));
subject.login(token);
System.out.println("认证状态:"+(subject.isAuthenticated()?"认证成功":"还未认证"));
}catch(UnknownAccountException e){
System.out.println("用户名错误");
/**
* 未进行md5加密时报IncorrectCredentialsException异常
* IncorrectCredentialsException是AuthenticationException子类
* 所以通用的话写AuthenticationException为好
*/
} catch (AuthenticationException e){
System.out.println("密码错误");
}
//测试授权
if(subject.isAuthenticated()){
//基于角色权限控制,判断几个权限就访问几次doGetAuthorizationInfo方法
//判断单个权限
System.out.println("是否具有admin权限:"+(subject.hasRole("admin")?"有":"没有"));
//判断任意一权限(或)
System.out.println("是否具有admin、user、super其中一个:");
List list=new ArrayList();
list.add("admin");
list.add("user");
list.add("super");
int i=0;
for (boolean b : subject.hasRoles(list)) {
System.out.println("是否具有"+list.get(i)+": "+(b?"具有":"没有"));
i++;
}
//判断是否同时具有所有权限(且)
System.out.println("是否同时具有admin和user:"+(subject.hasAllRoles(Arrays.asList("admin","user"))?"同时具有":"不是同时具有"));
}
}
}
认证状态:还未认证
数据库中
Tom ---- 7615a154b34f0a31f225dcfc681acbfc
认证状态:认证成功
Tom访问了doGetAuthorizationInfo()方法
是否具有admin权限:有
是否具有admin、user、super其中一个:
Tom访问了doGetAuthorizationInfo()方法
Tom访问了doGetAuthorizationInfo()方法
Tom访问了doGetAuthorizationInfo()方法
是否具有admin: 具有
是否具有user: 具有
是否具有super: 没有
Tom访问了doGetAuthorizationInfo()方法
Tom访问了doGetAuthorizationInfo()方法
是否同时具有admin和user:同时具有