Springboot 手动搭建项目 --shiro实现
项目git网址:https://github.com/David-BIQI/manage.git(项目使用比较新的springboot2.0 还有jdk8 )
参照的代码规范:https://github.com/xwjie/PLMCodeTemplate.git (这个是一套能够落地的代码规范,跟着风哥学习很多)
shiro的数据库设计
用户表、角色表、权限表、用户与角色中间表、角色与权限中间表
drop table if exists permission; drop table if exists role; drop table if exists role_to_permission; drop table if exists user_to_role; /*==============================================================*/ /* Table: permission */ /*==============================================================*/ create table permission ( id int not null auto_increment, name varchar(50) comment '权限名称', url varchar(100) not null comment '请求路径', permission varchar(150) not null comment '角色编码', status tinyint(1) default 1, created datetime default CURRENT_TIMESTAMP, createdby int, updated datetime default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, updatedby int default 0, remark varchar(50) default '', primary key (id) ); alter table permission comment '权限表'; /*==============================================================*/ /* Table: role */ /*==============================================================*/ create table role ( id int not null auto_increment, role_name varchar(100) not null comment '角色名称', role_code varchar(150) not null comment '角色编码', status tinyint(1) default 1, created datetime default CURRENT_TIMESTAMP, createdby int, updated datetime default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, updatedby int, remark varchar(50) default '', primary key (id) ); alter table role comment '角色表'; /*==============================================================*/ /* Table: role_to_permission */ /*==============================================================*/ create table role_to_permission ( id int not null auto_increment, permission_id varchar(100) not null comment '权限id', role_id varchar(150) not null comment '角色id', status tinyint(1) default 1, created datetime default CURRENT_TIMESTAMP, createdby int, updated datetime default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, updatedby int, primary key (id) ); alter table role_to_permission comment '角色与权限表'; /*==============================================================*/ /* Table: user_to_role */ /*==============================================================*/ create table user_to_role ( id int not null auto_increment, user_id varchar(100) not null, role_id varchar(150) not null, status tinyint(1) default 1, created datetime default CURRENT_TIMESTAMP, createdby int, updated datetime default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, updatedby int, primary key (id) ); alter table user_to_role comment '用户角色表';
shiro结合springboot
@Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { System.out.println("ShiroConfiguration.shirFilter()"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //拦截器. Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>(); // 配置不会被拦截的链接 顺序判断 filterChainDefinitionMap.put("/static/**", "anon"); //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 filterChainDefinitionMap.put("/logout", "logout"); //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> filterChainDefinitionMap.put("/**", "authc"); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/login"); // 登录成功后要跳转的链接 shiroFilterFactoryBean.setSuccessUrl("/main"); //未授权界面; shiroFilterFactoryBean.setUnauthorizedUrl("/403"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /** * 凭证匹配器 * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 * ) * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; // hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5("")); return hashedCredentialsMatcher; } @Bean public UserRealm myShiroRealm(){ UserRealm myShiroRealm = new UserRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); return securityManager; } /** * 开启shiro aop注解支持. * 使用代理方式;所以需要开启代码支持; * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean(name="simpleMappingExceptionResolver") public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() { SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理 mappings.setProperty("UnauthorizedException","403"); r.setExceptionMappings(mappings); // None by default r.setDefaultErrorView("error"); // No default r.setExceptionAttribute("ex"); // Default is "exception" //r.setWarnLogCategory("example.MvcLogger"); // No default return r; }
real的校验
@Slf4j public class UserRealm extends AuthorizingRealm { //注入角色权限等表 @Autowired private PermissionDao permissionDao; @Autowired private RoleDao roleDao; @Autowired private RoleToPermissionDao roleToPermissionDao; @Autowired private UserDao userDao; @Autowired private UserToRoleDao userToRoleDao; /** * 授权 * @param principals * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); User userInfo = (User)principals.getPrimaryPrincipal(); UserToRole userToRole = new UserToRole(); userToRole.setUserId(userInfo.getId()); List<UserToRole> roleList = userToRoleDao.select(userToRole); //获取role表和权限表-->设置到realm中去 List<Role> roles = new ArrayList<>(roleList.size()); //List<Role> roles = roleDao.selectAll(); roleList.forEach(item->{ roles.add(roleDao.selectByPrimaryKey(item.getRoleId())); }); roles.forEach(item->{ authorizationInfo.addRole(item.getRoleName()); RoleToPermission roleToPermission = new RoleToPermission(); roleToPermission.setStatus(BaseConstant.STATUS.YES); roleToPermission.setRoleId(item.getId()); List<RoleToPermission> select = roleToPermissionDao.select(roleToPermission); for (RoleToPermission itemRoleToPermission : select) { Permission permission = permissionDao.selectByPrimaryKey(itemRoleToPermission.getPermissionId()); authorizationInfo.addStringPermission(permission.getPermission()); } }); System.out.println(authorizationInfo.toString()); return authorizationInfo; } /** * @param token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("MyShiroRealm.doGetAuthenticationInfo()"); //获取用户的输入的账号. String username = (String)token.getPrincipal(); System.out.println(token.getCredentials()); //通过username从数据库中查找 User对象,如果找到,没找到. User user = new User(); user.setName(username); User userInfo = userDao.selectOne(user); System.out.println("----->>userInfo="+userInfo); if(userInfo == null){ return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( userInfo, //用户名 userInfo.getPassword(), //密码 ByteSource.Util.bytes("123"),//salt=username+salt getName() //realm name ); return authenticationInfo; } }
最后shiro通过注解实现
shiro实现实现拦截器的功能,自身集成session的管理等,通过注解权限好上手,通过jdbc配置配置权限就要做好数据库权限表的维护等