一、Shiro简介
shiro是一个Apache的开源安全框架,提供认证,授权,企业会话管理,安全加密,缓存管理等
二、Shiro整体架构
最上面部分 操作用户
操作核心(Security Manager)
1、authenticator : 认证器(登录登出)
2、authorizer : 授权器(赋予主体有哪些权限)
3、session manager :session管理器(可以在不使用任何框架的情况下管理session)
4、cache manager : 缓存管理器 (管理操作缓存数据)
5、session dao : 提供session操作(增删改查)
6、realms : shiro和桥梁 认证信息权限数据角色数据都是通过它来获取
最右边是shiro的加密工具
底部数据库部分
三、Shiro认证 、授权、自定义realm
认证流程图
1、使用SimpleAccountRealm实现认证授权过程
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>
AuthenticatorTest
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 AuthenticatorTest { SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm(); @Before public void addUser(){ simpleAccountRealm.addAccount("Mark","1234"); } @Test public void TestAuthenticator(){ //1.构建 securitymanager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(simpleAccountRealm); //2.主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("Mark","1234"); subject.login(token); System.out.println("isAuthenticated: "+subject.isAuthenticated()); } }
账号错误,会抛出Realm不能识别的账号异常
密码错误,会抛出不正确的认证异常
另外,shiro还提供了登出功能
subject.logout(); System.out.println("isAuthenticated: "+subject.isAuthenticated());
2、使用iniRealm实现认证授权过程
ini文件内容
[users]
Mark=1234,admin
[roles]
admin=user:delete
IniRealmTest
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; public class IniRealmTest { IniRealm iniRealm = new IniRealm("classpath:user.ini"); @Test public void TestIniRealm(){ //1.构建 securitymanager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(iniRealm); //2.主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("Mark","1234"); subject.login(token); System.out.println("isAuthenticated: "+subject.isAuthenticated()); subject.checkRole("admin"); subject.checkPermission("user:delete"); /*subject.logout(); System.out.println("isAuthenticated: "+subject.isAuthenticated());*/ } }
3、使用JDBCRealm实现认证授权过程
自定义表结构
user
role
permissions
JDBCRealmTest
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.realm.text.IniRealm; import org.apache.shiro.subject.Subject; import org.junit.Test; public class JDBCRealmTest { DruidDataSource dataSource = new DruidDataSource(); { dataSource.setUrl("jdbc:mysql://localhost:3306/jdbcrealm"); dataSource.setUsername("root"); dataSource.setPassword("1234"); } @Test public void TestJDBCRealm(){ JdbcRealm JdbcRealm = new JdbcRealm(); JdbcRealm.setDataSource(dataSource); JdbcRealm.setPermissionsLookupEnabled(true); //自定义sql语句 String sql = "select password from user where user_name = ?"; JdbcRealm.setAuthenticationQuery(sql); String roleSql = "select role from role where user_name = ?"; JdbcRealm.setUserRolesQuery(roleSql); String permissionSql = "select permissions from permissions where role = ?"; JdbcRealm.setPermissionsQuery(permissionSql); //1.构建 securitymanager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(JdbcRealm); //2.主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("xiaoming","1234"); subject.login(token); System.out.println("isAuthenticated: "+subject.isAuthenticated()); subject.checkRole("user"); subject.checkPermission("login"); } }
4、自定义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.crypto.hash.Md5Hash; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public class CustomRealm extends AuthorizingRealm { Map<String,String> userMap = new HashMap<String, String>(16); { //81dc9bdb52d04dc20036dbd8313ed055 userMap.put("Mark","f2d9ffba24994ac1cbeff23d94ddb62a"); super.setName("CustomRealm"); //Thread.currentThread().setName();为当前线程设置名称 } protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); //模拟从数据库或缓存中获取角色数据 Set<String> roles = getRolesByUsername(username); Set<String> permissions = getPermissionsByUsername(username); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(roles); info.setStringPermissions(permissions); return info; } private Set<String> getPermissionsByUsername(String username) { Set<String> set = new HashSet<String>(); set.add("user:delete"); set.add("user:update"); return set; } private Set<String> getRolesByUsername(String username) { Set<String> set = new HashSet<String>(); set.add("admin"); set.add("user"); return set; } protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //1、AuthenticationToken 主体传过来的认证信息中,获取用户名 String username = (String)token.getPrincipal(); //2、通过用户名到数据库中获取凭证 String password = getPasswordByUsername(username); if(password==null){ return null; } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo("Mark",password,"CustomRealm"); info.setCredentialsSalt(ByteSource.Util.bytes("Mark")); return info; } //模拟数据库查询凭证 private String getPasswordByUsername(String username) { return userMap.get(username); } public static void main(String[] args) { Md5Hash md5Hash = new Md5Hash("1234","Mark"); System.out.println(md5Hash.toString()); } }
测试
import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.subject.Subject; import org.junit.Test; import realm.CustomRealm; public class CustomRealmTest { CustomRealm customRealm = new CustomRealm(); @Test public void TestIniRealm(){ //1.构建 securitymanager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(customRealm); HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); matcher.setHashAlgorithmName("MD5"); matcher.setHashIterations(1); customRealm.setCredentialsMatcher(matcher); //2.主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("Mark","1234"); subject.login(token); System.out.println("isAuthenticated: "+subject.isAuthenticated()); subject.checkRole("admin"); subject.checkPermission("user:delete"); } }
来源:CSDN
作者:山岭巨人杨尚桑
链接:https://blog.csdn.net/qq_44868502/article/details/103874863