Apache Shiro 是 Java 的一个安全框架。
Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。
Shiro的内置Realm:IniRealm和JdbcRealm
编写测试案例之前需要添加shiro的相关依赖:
<dependencies> <dependency> <groupId>org.apache.shirogroupId> <artifactId>shiro-coreartifactId> <version>1.4.0version> dependency> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>RELEASEversion> dependency> <dependency> <groupId>mysqlgroupId> <artifactId>mysql-connector-javaartifactId> <version>5.1.45version> dependency> <dependency> <groupId>com.alibabagroupId> <artifactId>druidartifactId> <version>1.1.6version> dependency> dependencies>
项目的目录结构:
一、使用SimpleAccountRealm测试认证授权
SimpleAccountRealm功能简单,不能实现权限功能,很多时候需要自己重新定义。
package com.czhappy.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; /** * 测试shiro认证授权 */ public class AuthenticationTest { SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm(); @Before public void addUser(){ simpleAccountRealm.addAccount("chen", "123456", "admin"); } @Test public void testAuthentication(){ //创建SecurityManager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(simpleAccountRealm); //主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("chen", "123456"); subject.login(token); System.out.println("isAuthenticated="+subject.isAuthenticated()); //验证角色授权 subject.checkRole("admin"); //退出 subject.logout(); } }
二、使用IniRealm测试认证授权
编写user.ini文件:
[users] chen=123456,admin [roles] admin=user:delete,user:update
编写测试案例:
package com.czhappy.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; /** * IniRealm测试 */ public class IniRealmTest { @Test public void testAuthentication() { IniRealm iniRealm = new IniRealm("classpath:user.ini"); //创建SecurityManager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(iniRealm); //主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("chen", "123456"); subject.login(token); System.out.println("isAuthenticated=" + subject.isAuthenticated()); subject.checkRole("admin"); subject.checkPermission("user:delete"); } }
三、使用JdbcRealm测试认证授权
使用JdbcRealm需要连接数据操作,在此我们新建三张表
由于使用的是系统自己JdbcRealm,操作数据库需要和源码中的表名一致.
package com.czhappy.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.realm.text.IniRealm; import org.apache.shiro.subject.Subject; import org.junit.Test; /** * JdbcRealm测试 */ public class JdbcRealmTest { DruidDataSource dataSource = new DruidDataSource(); { dataSource.setUrl("jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=true"); dataSource.setUsername("root"); dataSource.setPassword("root"); } @Test public void testAuthentication() { JdbcRealm jdbcRealm = new JdbcRealm(); jdbcRealm.setDataSource(dataSource); //权限开关打开,默认是关闭的 jdbcRealm.setPermissionsLookupEnabled(true); //创建SecurityManager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(jdbcRealm); //主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("chen", "123456"); subject.login(token); System.out.println("isAuthenticated=" + subject.isAuthenticated()); subject.checkRole("admin"); subject.checkPermission("user:select"); } }
四、自己编写sql的调用JdbcRealm认证授权
新建2张表
package com.czhappy.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; /** * JdbcRealm测试 */ public class SelfJdbcRealmTest { DruidDataSource dataSource = new DruidDataSource(); { dataSource.setUrl("jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=true"); dataSource.setUsername("root"); dataSource.setPassword("root"); } @Test public void testAuthentication() { JdbcRealm jdbcRealm = new JdbcRealm(); jdbcRealm.setDataSource(dataSource); //权限开关打开,默认是关闭的 jdbcRealm.setPermissionsLookupEnabled(true); String sql = "select password from test_user where user_name = ?"; jdbcRealm.setAuthenticationQuery(sql); String roleSql = "select role_name from test_user_roles where user_name = ?"; jdbcRealm.setUserRolesQuery(roleSql); //创建SecurityManager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(jdbcRealm); //主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "654321"); subject.login(token); System.out.println("isAuthenticated=" + subject.isAuthenticated()); subject.checkRole("user"); // subject.checkPermission("user:select"); } }
权限的测试可以参照角色,创建表、编写相关的sql语句
五、自定义Realm实现认证授权
package com.czhappy.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.AuthenticatingRealm; 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; /** * 自定义Realm */ public class CustomRealm extends AuthorizingRealm { MapuserMap = new HashMap (16); { userMap.put("chen", "123456"); super.setName("customRealm"); } //角色权限验证 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String userName = (String) principalCollection.getPrimaryPrincipal(); //从数据库或者缓存中获取角色数据 Set roleSet = getRolesByUserName(userName); //从数据库或者缓存中获取权限数据 Set permissionSet = getPermissionsByUserName(userName); SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); simpleAuthorizationInfo.setRoles(roleSet); simpleAuthorizationInfo.setStringPermissions(permissionSet); return simpleAuthorizationInfo; } /** * 模拟从数据库或者缓存中获取权限数据 * @param userName * @return */ private Set getPermissionsByUserName(String userName) { Set sets = new HashSet (); sets.add("user:add"); sets.add("user:delete"); return sets; } /** * 模拟从数据库或者缓存中获取角色数据 * @param userName * @return */ private Set getRolesByUserName(String userName) { Set sets = new HashSet (); sets.add("admin"); sets.add("user"); return sets; } //登录验证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //从主体传过来的认证信息中获取用户名 String userName = (String) authenticationToken.getPrincipal(); //通过用户名到数据库中获取凭证 String password = getPasswordByUsername(userName); if(password == null){ return null; } SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo (userName, password, "customRealm"); return simpleAuthenticationInfo; } /** * 模拟数据库访问 * @param userName * @return */ private String getPasswordByUsername(String userName) { return userMap.get(userName); } }
测试认证授权:
package com.czhappy.test; import com.czhappy.realm.CustomRealm; 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 CustomRealmTest { @Test public void testAuthentication() { CustomRealm customRealm = new CustomRealm(); //创建SecurityManager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(customRealm); //主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("chen", "123456"); subject.login(token); System.out.println("isAuthenticated=" + subject.isAuthenticated()); subject.checkRole("admin"); subject.checkPermissions("user:delete", "user:add"); } }