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配置配置權限就要做好數據庫權限表的維護等
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM