单数据源的情况
shiro.ini
[main]
#实例化数据源
dataSource=com.alibaba.druid.pool.DruidDataSource
#设置数据源的连接参数
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro?useSSL=false&useUnicode=true&characterEncoding=UTF-8
dataSource.username=root
dataSource.password=123456
#采用shiro提供的jdbc访问类(JdbcRealm)操作数据库查询
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm
多数据源的情况
shiro.ini
[main]
#第一个数据源的设置
#实例化数据源
dataSource1=com.alibaba.druid.pool.DruidDataSource
#设置数据源的连接参数
dataSource1.driverClassName=com.mysql.jdbc.Driver
dataSource1.url=jdbc:mysql://localhost:3306/shiro?useSSL=false&useUnicode=true&characterEncoding=UTF-8
dataSource1.username=root
dataSource1.password=123456
#采用shiro提供的jdbc访问类(JdbcRealm)操作数据库查询
jdbcRealm1=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm1.dataSource=$dataSource1
#第二个数据源的设置
dataSource2=com.alibaba.druid.pool.DruidDataSource
#设置数据源的连接参数
dataSource2.driverClassName=com.mysql.jdbc.Driver
dataSource2.url=jdbc:mysql://localhost:3306/shiro_test?useSSL=false&useUnicode=true&characterEncoding=UTF-8
dataSource2.username=root
dataSource2.password=123456
#采用shiro提供的jdbc访问类操作数据库查询
jdbcRealm2=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm2.dataSource=$dataSource2
#加入jdbcRealm
securityManager.realms=$jdbcRealm1,$jdbcRealm2
#设置认证策略
#认证策略:所有的数据源要全部认证成功才算成功
anthenticate=org.apache.shiro.authc.pam.AllSuccessfulStrategy
#设置指定的认证策略
securityManager.authenticator.authenticationStrategy=$anthenticate
测试代码
package com.shiro;
import org.apache.shiro.SecurityUtils;
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 Demo {
public static void main(String[] args) {
// 加载shiro.ini配置文件
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 创建SecurityManager对象
SecurityManager instance = factory.getInstance();
// 将SecurityManager设置到当前开发环境中来
SecurityUtils.setSecurityManager(instance);
// 获取代表当前用户数据库数据的subject对象
Subject subject = SecurityUtils.getSubject();
// 把需要登录的数据封装成token凭证(令牌)
UsernamePasswordToken token = new UsernamePasswordToken("zyy", "123456");
// 通过subject的login方法验证token是否和数据库里面的数据一致
try{
subject.login(token);
if (subject.isAuthenticated()){
System.out.println("登陆成功");
}
}catch (Exception e){
e = new Exception("账户名或者密码错误");
e.printStackTrace();
}
}
}
查看org.apache.shiro.realm.jdbc.JdbcRealm源码
protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";
protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";
protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";
可以看出 数据库的表名和字段名有要求 表名要是users 两个字段分别是username和password
这个是可以改变的 只需要我们不使用官方的JdbcRealm 所以我们自定义一个自己的JdbcRealm
注意 自己的JdbcRealm要继承和官方一样的AuthorizingRealm类
MyRealm
package com.realm;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MyRealm extends AuthorizingRealm {
// 注意这里一定要声明dataSource 为了在配置文件中注入 同时要加上set方法
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
// 用来给用户授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
// 用来认证用户信息(登录)
// subject.login(token)传入的参数会被AuthenticationToken接收
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String name = (String) authenticationToken.getPrincipal();
Connection con = null;
try {
con = dataSource.getConnection();
PreparedStatement pstmt = con.prepareStatement("select `name`,password from users where `name`=?");
pstmt.setString(1,name);
ResultSet re = pstmt.executeQuery();
while(re.next()){
String userName = re.getString("name");
String password = re.getString("password");
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, password, "");
return info;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
}
shiro.ini
[main]
#第一个数据源的设置
#实例化数据源
dataSource1=com.alibaba.druid.pool.DruidDataSource
#设置数据源的连接参数
dataSource1.driverClassName=com.mysql.jdbc.Driver
dataSource1.url=jdbc:mysql://localhost:3306/shiro_test?useSSL=false&useUnicode=true&characterEncoding=UTF-8
dataSource1.username=root
dataSource1.password=123456
#采用自定义的操作数据库查询
jdbcRealm1=com.realm.MyRealm
jdbcRealm1.dataSource=$dataSource1
#加入jdbcRealm
securityManager.realms=$jdbcRealm1
使用MD5加密算法
shiro.ini
[main]
#第一个数据源的设置
#实例化数据源
dataSource1=com.alibaba.druid.pool.DruidDataSource
#设置数据源的连接参数
dataSource1.driverClassName=com.mysql.jdbc.Driver
dataSource1.url=jdbc:mysql://localhost:3306/shiro_test?useSSL=false&useUnicode=true&characterEncoding=UTF-8
dataSource1.username=root
dataSource1.password=123456
#配置加密对象
hcm=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#给hcm对象设置加密的方式MD5
hcm.hashAlgorithmName=Md5
#加盐的迭代加密次数
hcm.hashIterations=3
#采用自定义的操作数据库查询
jdbcRealm1=com.realm.MyRealm
jdbcRealm1.dataSource=$dataSource1
#给自定义的Realm关联加密对象
jdbcRealm1.credentialsMatcher=$hcm
#加入jdbcRealm
securityManager.realms=$jdbcRealm1
MyRealm
package com.realm;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MyRealm extends AuthorizingRealm {
// 注意这里一定要声明dataSource 为了在配置文件中注入 同时要加上set方法
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
// 用来给用户授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
// 用来认证用户信息(登录)
// subject.login(token)传入的参数会被AuthenticationToken接收
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String name = (String) authenticationToken.getPrincipal();
Connection con = null;
try {
con = dataSource.getConnection();
PreparedStatement pstmt = con.prepareStatement("select `name`,password from users where `name`=?");
pstmt.setString(1,name);
ResultSet re = pstmt.executeQuery();
while(re.next()){
String userName = re.getString("name");
String password = re.getString("password");
// 这里要设置加密的盐
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, password, ByteSource.Util.bytes("006876"),"");
return info;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
}
加密
Md5Test
import org.apache.shiro.crypto.hash.Md5Hash;
public class Md5Test {
public static void main(String[] args) {
Md5Hash md5Hash = new Md5Hash("123456", "006876", 3);
System.out.println(md5Hash);
}
}