天天看點

springboot運用shiro簡單控制權限

shiro簡單介紹

shiro是一個功能強大的java安全架構,主要部分構成認證、授權、加密和會話管理等。

1.認證:身份認證,驗證登入使用者是否正确等。

2.授權:授予權利通路某個頁面或接口。

3.加密:shiro提供加密服務。保護資料的安全性,如密碼加密存儲到資料庫,而不是明文存儲。

4.會話管理:使用者登入了一次就是會話,在一定時間内,使用者的所有資訊都儲存在會話中。

spring裝配shiro,基于javaBean的寫法

1.将SecurityManager交給spring處理

@Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm());
        return securityManager;
    }
           

2.建立realm

@Bean
    public ShiroRealm shiroRealm(){
        ShiroRealm shiroRealm=new ShiroRealm();
        return shiroRealm;
    }
           

3.配置ShiroFilterFactoryBean

@Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        System.out.println("---shiroFIlter---");

        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();

        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
        //注意過濾器配置順序 不能颠倒
        //配置退出 過濾器,其中的具體的退出代碼Shiro已經替我們實作了,登出後跳轉配置的loginUrl
        // 配置不會被攔截的連結 順序判斷
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/favicon.ico", "anon");
        //攔截其他是以接口
        filterChainDefinitionMap.put("/**", "authc");
        //配置shiro預設登入界面位址,前後端分離中登入界面跳轉應由前端路由控制,背景僅傳回json資料
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登入成功後要跳轉的連結 自行處理。不用shiro進行跳轉
        // shiroFilterFactoryBean.setSuccessUrl("user/index");
        //未授權界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/user/unauth");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return  shiroFilterFactoryBean;
    }
           

4.建立代理bean通知類和開起shiro aop切面程式設計支援,注:往spring裡面注入這兩個bean。才能用注解的方式去對權限做校驗。

@Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
    /**
     * 開啟shiro aop注解支援
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor sourceAdvisor=new AuthorizationAttributeSourceAdvisor();
        sourceAdvisor.setSecurityManager(securityManager);
        return sourceAdvisor;
    }
           

自定義實作realm,實作認證和授權的過程

1.認證過程

認證我們需要做的是通過使用者名的比對。從資料庫中查詢相應的使用者。并放入SimpleAuthenticationInfo中,剩下的交給shiro去認證校驗。

myrealm的認證:

@Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String)authenticationToken.getPrincipal();
        System.out.println(username);
        ShiroUser shiroUser=shiroUserMapper.selectByUserName(username);
        if (shiroUser==null){
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
                shiroUser,
                shiroUser.getPassword(),
                getName()
        );
        return authenticationInfo;
    }
}
           

查詢語句:

<select id="selectByUserName" parameterType="java.lang.String" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from shiro_user
    where username = #{userName,jdbcType=VARCHAR}
  </select>
           

2.授權過程

授權需要我們做的是通過使用者id查詢角色和權限,将權限和角色注入到AuthorizationInfo

授權:

@Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("--權限注入--");
        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
        ShiroUser shiroUser= (ShiroUser) principalCollection.getPrimaryPrincipal();
        //注入角色權限
     try {
         List<ShiroRole> shiroRoles=shiroUserMapper.selectRoleByUser(shiroUser.getId());
         for (ShiroRole s:shiroRoles){
             simpleAuthorizationInfo.addRole(s.getRoleName());
         }
         List<ShiroFunction> shiroFunctions =shiroUserMapper.queryByUserId(shiroUser.getId());
         for(ShiroFunction functions:shiroFunctions){
             simpleAuthorizationInfo.addStringPermission(functions.getPermissionName());

         }
     }catch (Exception e){
         e.printStackTrace();
     }
        return simpleAuthorizationInfo;
    }
           

查詢語句:

<select id="selectRoleByUser" parameterType="java.lang.Integer" resultType="com.example.pojo.ShiroRole">
    select role_name,role_id,shiro_role.create_time
    from shiro_role
    left join shiro_user_role r on shiro_role.id = r.role_id
    left join shiro_user u on r.user_id = u.id
    where u.id=#{id,jdbcType=INTEGER}
  </select>
    <select id="queryByUserId" parameterType="java.lang.Integer" resultType="com.example.pojo.ShiroFunction">
      select shiro_function.id,shiro_function.create_time,shiro_function.function_name,shiro_function.permission_name,shiro_function.pid
    from shiro_function
    left join shiro_role_function r on shiro_function.id = r.function_id
    left join shiro_user_role u on u.role_id = r.role_id
    left join shiro_user su on u.user_id = su.id
    where su.id=#{id,jdbcType=INTEGER}
  </select>
           

結語:

這樣一個簡單的shiro權限的配置和注入就完成了,基本能夠控制使用者登入,根據使用者的不用配置設定不同的權限和角色,達到對權限的控制。

demo位址:http://114.115.154.147/ 使用者名:admin 密碼:123 原諒沒有域名。