springboot 整合shiro
一、创建数据库
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for mz_permission -- ---------------------------- DROP TABLE IF EXISTS `mz_permission`; CREATE TABLE `mz_permission` ( `id` bigint(8) NOT NULL AUTO_INCREMENT, `permission_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '权限名称', `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '资源地址', `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '权限描述', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `modify_time` datetime DEFAULT NULL COMMENT '修改时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for mz_permission_role -- ---------------------------- DROP TABLE IF EXISTS `mz_permission_role`; CREATE TABLE `mz_permission_role` ( `role_id` bigint(8) DEFAULT NULL COMMENT '角色ID', `permission_id` bigint(8) DEFAULT NULL COMMENT '权限ID' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for mz_role -- ---------------------------- DROP TABLE IF EXISTS `mz_role`; CREATE TABLE `mz_role` ( `id` bigint(8) NOT NULL AUTO_INCREMENT, `role_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '角色名称', `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '角色描述', `create_time` datetime DEFAULT NULL, `modify_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for mz_user -- ---------------------------- DROP TABLE IF EXISTS `mz_user`; CREATE TABLE `mz_user` ( `id` bigint(8) NOT NULL AUTO_INCREMENT, `user_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '用户名', `password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密码', `nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '昵称', `sex` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '性别', `age` int(2) DEFAULT NULL COMMENT '年龄', `token` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL, `salt` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL, `create_time` datetime DEFAULT NULL, `modify_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -- ---------------------------- -- Table structure for mz_user_role -- ---------------------------- DROP TABLE IF EXISTS `mz_user_role`; CREATE TABLE `mz_user_role` ( `user_id` bigint(8) DEFAULT NULL COMMENT '用户ID', `role_id` bigint(20) DEFAULT NULL COMMENT '角色ID' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
二、代码实现
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency>
1.自定义realm
import com.mz.cloud.model.MzUser; import com.mz.cloud.service.MzUserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; import java.util.Set; public class CustomRealm extends AuthorizingRealm { @Autowired private MzUserService mzUserService; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String userName = (String) SecurityUtils.getSubject().getPrincipal(); //从数据库或者缓存中获取角色数据 Set<String> roles = mzUserService.getRolesByUserName(userName); //获取权限数据 Set<String> permissions = mzUserService.getPermissionByUserName(userName); SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); simpleAuthorizationInfo.setRoles(roles); simpleAuthorizationInfo.setStringPermissions(permissions); return simpleAuthorizationInfo; } //认证登录 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //获取登录的用户名和密码 String userName = (String) authenticationToken.getPrincipal(); String password = new String((char[]) authenticationToken.getCredentials()); //根据用户名获取用户信息 MzUser mzUser = mzUserService.queryByUserName(userName); if (mzUser == null) { throw new AccountException("用户不存在"); }else if (!mzUser.getPassword().equals(MD5Pwd(userName, password))) { throw new AccountException("密码不正确"); } return new SimpleAuthenticationInfo(userName, mzUser.getPassword(), ByteSource.Util.bytes(userName + "salt"), getName()); } //注册的时候调用这个方法 public static String MD5Pwd(String userName, String password) { //salt盐:userName+salt String md5Pwd = new SimpleHash("MD5", password, ByteSource.Util.bytes(userName + "salt"), 2).toHex(); return md5Pwd; } public static void main(String[] args) { System.out.println(MD5Pwd("test", "123456")); } }
2.设置配置信息,注入spring容器
@Configuration public class ShiroConfig { @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); // 登录的url shiroFilterFactoryBean.setLoginUrl("/mz/user/login"); // 登录成功后跳转的url shiroFilterFactoryBean.setSuccessUrl("/mz/index"); // 权限拒绝时跳转的url shiroFilterFactoryBean.setUnauthorizedUrl("/mz/unauthorize"); // 定义请求拦截规则,key是正则表达式用于匹配访问的路径,value则用于指定使用什么拦截器进行拦截 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); //所有的url必须通过认证才能访问,authc表示需要认证才能访问 filterChainDefinitionMap.put("/**", "authc"); // anon表示不拦截 filterChainDefinitionMap.put("/mz/user/login", "anon"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager() { DefaultSecurityManager defaultSecurityManager = new DefaultWebSecurityManager(); defaultSecurityManager.setRealm(customRealm()); return defaultSecurityManager; } @Bean public CustomRealm customRealm() { CustomRealm customRealm = new CustomRealm(); //告诉realm使用credentialsMatcher加密算法类来验证密文 customRealm.setCredentialsMatcher(hashedCredentialsMatcher()); customRealm.setCachingEnabled(false); return customRealm; } @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); //散列算法:这里使用MD5算法 hashedCredentialsMatcher.setHashAlgorithmName("md5"); //散列的次数,比如散列两次,相当于md5(md5("")); hashedCredentialsMatcher.setHashIterations(2); //storedCredentialsHexEncoded默认是true,此时的密码加密用的是Hex编码,false时用Base64编码 hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true); return hashedCredentialsMatcher; } /* * 开启@RequirePermission注解的配置,要结合DefaultAdvisorAutoProxyCreator一起使用,或者导入aop的依赖 */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } }
代码出处:https://www.jianshu.com/p/63449d21b4b9,https://blog.51cto.com/zero01/2172662