一.Shiro的认证逻辑

代码演示
- 先在pom中配置依赖
<dependencies>
<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>
</dependencies>
- 新建测试类AuthenticationTest
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;
public class AuthenticationTest {
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();
UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
subject.login(token);
System.out.println("isAuthenticated:"+subject.isAuthenticated());
subject.logout();
System.out.println("isAuthenticated:"+subject.isAuthenticated());
}
}
- 测试结果

- 从代码中分析认证逻辑

二.Shiro的授权逻辑

代码演示
- 在认证的代码上修改
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;
public class AuthenticationTest {
SimpleAccountRealm simpleAccountRealm=new SimpleAccountRealm();
@Before
public void addUser(){
//添加用户名,密码,用户角色
simpleAccountRealm.addAccount("Mark","123456","admin");
}
@Test
public void testAuthentication(){
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//2.主体认证提交请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
subject.login(token);
System.out.println("isAuthenticated:"+subject.isAuthenticated());
//检查是否是管理员角色
subject.checkRole("admin");
}
}
- 从代码中分析授权逻辑

三.自定义Realm
1.创建自定义的CustomRealm

CustomRealm继承AuthorizingRealm类,该类有doGetAuthorizationInfo()、doGetAuthenticationInfo()方法。doGetAuthorizationInfo()用来编写授权逻辑,doGetAuthenticationInfo()方法用来编写认证逻辑。
public class CustomRealm extends AuthorizingRealm {
//授权逻辑
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证逻辑
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
return null;
}
}
2.编写认证逻辑,因为是简单的测试,所以没有连接数据库,数据库用Map来模拟
public class CustomRealm extends AuthorizingRealm {
/**
* 模拟数据库中的数据
*/
Map<String,String> userMap=new HashMap<>(16);
{
userMap.put("Mark","123456");
super.setName("customRealm");
}
//授权逻辑
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证逻辑
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;
}
/**
* 模拟数据库查询凭证
* @param userName
* @return
*/
private String getPasswordByUserName(String userName) {
return userMap.get(userName);
}
}
3.编写测试类CustomRealmTest

public class CustomRealmTest {
@Test
public void testAuthentication(){
CustomRealm customRealm=new CustomRealm();
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
//2.主体认证提交请求,主体授权
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
subject.login(token);
System.out.println("isAuthenticated:"+subject.isAuthenticated());
}
}
4.测试结果

5.编写授权逻辑
//授权逻辑
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;
}
/**
* 模拟数据库查询角色权限
* @param userName
* @return
*/
private Set<String> getPermissionsByUserName(String userName) {
Set<String> sets=new HashSet<>();
sets.add("user:delete");
sets.add("user:add");
return sets;
}
/**
* 模拟数据库查询角色
* @param userName
* @return
*/
private Set<String> getRolesByUserName(String userName) {
Set<String> sets=new HashSet<>();
sets.add("admin");
sets.add("user");
return sets;
}
6.测试
@Test
public void testAuthentication(){
CustomRealm customRealm=new CustomRealm();
//1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
//2.主体认证提交请求,主体授权
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
subject.login(token);
System.out.println("isAuthenticated:"+subject.isAuthenticated());
subject.checkRole("admin");
subject.checkPermissions("user:add","user:delete");
System.out.println("没有报错,说明正确");
}
结果

把user:add改为user:update,结果为


被折叠的 条评论
为什么被折叠?



