1.shiro整体架构
1.Authenticator=>认证器:负责用户登录登出
2.Authoorizer=>授权器:shiro给用户授权
3.Session Manager=>Session管理机制
4.SessionDao=>负责增删改查
5.Pluggable Realms=>与数据库交互,获取权限信息
6.Cryptography=>加密
2.Shiro认证
1.创建模版:
1.pom.xml添加依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
2.创建测试类
package com.imooc.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;
/**
* Created by fly on 2018/4/18.
*/
public class AuthenticationTest {
//暂时使用SimpleAccountRealm
SimpleAccountRealm simpleAccountRealm=new SimpleAccountRealm();
//创建一个用户
@Before
public void addUser(){
simpleAccountRealm.addAccount("Mark","123456");
}
@Test
public void testAuthentication(){
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject=SecurityUtils.getSubject();//注意使用shiro下的Subject
UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
subject.login(token);
System.out.println("isAuthenticated:"+subject.isAuthenticated());
subject.logout();
System.out.println("isAuthenticated:"+subject.isAuthenticated());
}
}
认证结果:
2.Shiro授权
1.给用户赋予一个角色
2.验证是否拥有该角色
结果:
若主体角色错误(异常)
扩展
可同时添加多个角色,check多个角色
Shiro自定义Realm
内置Realm:
1.IniRealm
2.JdbcRealm
1.IniRealm测试类
目录结构
创建IniRealmTest
package com.imooc.test;
import org.apache.shiro.SecurityUtils;
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;
import org.junit.Test;
/**
* Created by fly on 2018/4/18.
*/
public class IniRealTest {
//创建IniRealm
IniRealm iniRealm=new IniRealm("classpath:user.ini");
@Test
public void testAuthentication(){
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
defaultSecurityManager.setRealm(iniRealm);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject=SecurityUtils.getSubject();//注意使用shiro下的Subject
UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
subject.login(token);
System.out.println("isAuthenticated:"+subject.isAuthenticated());
//权限验证
subject.checkRole("admin");
//是否具备某权限
subject.checkPermission("user:delete");
}
}
创建user.ini
[users]
Mark=123456,admin
[roles]
admin=user:delete
运行结果
2.JdbcRealm
在pom.xml中导入mysql支持和datasource数据源
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
</dependencies>
JdbcRealmTest类
package com.imooc.test;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
/**
* Created by fly on 2018/4/19.
*/
public class JdbcRealmTest {
//创建jdbc数据源
DruidDataSource dataSource=new DruidDataSource();
//设置jdbc入口
{
dataSource.setUrl("jdbc:mysql://localhost:3306/shiro_test");
dataSource.setUsername("root");
dataSource.setPassword("123456");
}
@Test
public void testAuthentication(){
//创建JdbcRealm
JdbcRealm jdbcRealm=new JdbcRealm();
//设置JdbcRealm数据源
jdbcRealm.setDataSource(dataSource);
//设置权限开关(默认为false)
jdbcRealm.setPermissionsLookupEnabled(true);
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
defaultSecurityManager.setRealm(jdbcRealm);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject=SecurityUtils.getSubject();//注意使用shiro下的Subject
UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","123456");
subject.login(token);
System.out.println("isAuthenticated:"+subject.isAuthenticated());
//验证角色
subject.checkRole("admin");
//验证权限
subject.checkPermission("user:delete");
}
}
如果使用shiro默认的查询语句,就根据shiro查询语句创建表
注意:如果不设置开关 subject.checkPermission("user:delete");将报错
自定义sql语句查询
3.自定义Realm
创建自定义CustomRealm和测试类CustomRealmTest
没有从数据库查询,使用Map和Set进行模拟查询
CustomRealm
package com.imooc.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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Created by fly on 2018/4/19.
*/
public class CustomRealm extends AuthorizingRealm {
Map<String,String> userMap=new HashMap<String, String>(16);
{
userMap.put("Mark","123456");
super.setName("customRealm");
}
//授权方法
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String userName=(String) principalCollection.getPrimaryPrincipal();
//从数据库或者缓存中获取角色数据
Set<String> roles=getRolesByUserName(userName);
//从数据库或者缓存中获取权限数据
Set<String> permissions=getPermissionsByUserName(userName);
SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setStringPermissions(permissions);
simpleAuthorizationInfo.setRoles(roles);
return simpleAuthorizationInfo;
}
//模拟数据库获取角色数据
private Set<String> getPermissionsByUserName(String userName) {
Set<String> sets=new HashSet<String>();
sets.add("user:delete");
sets.add("user:select");
return sets;
}
//模拟数据库获取角色数据
private Set<String> getRolesByUserName(String userName) {
Set<String> sets=new HashSet<String>();
sets.add("admin");
sets.add("user");
return sets;
}
//认证方法
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.从主体穿过来的认证信息中,获得用户名
String userName=(String) authenticationToken.getPrincipal();
//2.通过用户名到数据库中获取凭证
String password=getPasswordByUserName(userName);
if(password==null){
return null;
}
SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo("Mark",password,"customRealm");
return authenticationInfo;
}
//模拟数据库查询
private String getPasswordByUserName(String userName) {
return userMap.get(userName);
}
}
CustomRealmTest
package com.imooc.test;
import com.imooc.realm.CustomRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
/**
* Created by fly on 2018/4/19.
*/
public class CustomReamlTest {
@Test
public void testAuthentication(){
//创建CustomRealm
CustomRealm customRealm=new CustomRealm();
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject=SecurityUtils.getSubject();//注意使用shiro下的Subject
UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
subject.login(token);
System.out.println("isAuthenticated:"+subject.isAuthenticated());
subject.checkRole("admin");
subject.checkPermissions("user:delete","user:select");
}
}
Shiro加密
1.Shiro散列配置
HashedCredentialsMatcher
自定义Realm中使用散列
盐的使用
在验证方法中设置加密类型,加密次数
HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("md5");//设置加密方法
matcher.setHashIterations(1);//设置加密次数
customRealm.setCredentialsMatcher(matcher);
在Realm中设置盐等参数
//设置盐
authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("Mark"));
============未完待续=================