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配置配置权限就要做好数据库权限表的维护等
 
 
posted @ 2018-11-05 22:07  七分饱  阅读(1065)  评论(0编辑  收藏  举报