国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

sSpring Boot多模塊+ Shiro + Vue:前后端分離登陸整合,權(quán)限認(rèn)證(一)

macg0406 / 1177人閱讀

摘要:前言本文主要使用來(lái)實(shí)現(xiàn)前后端分離的認(rèn)證登陸和權(quán)限管理,適合和我一樣剛開始接觸前后端完全分離項(xiàng)目的同學(xué),但是你必須自己搭建過(guò)前端項(xiàng)目和后端項(xiàng)目,本文主要是介紹他們之間的互通,如果不知道這么搭建前端項(xiàng)目的同學(xué)可以先找別的看一下。

前言

本文主要使用spring boot + shiro + vue來(lái)實(shí)現(xiàn)前后端分離的認(rèn)證登陸和權(quán)限管理,適合和我一樣剛開始接觸前后端完全分離項(xiàng)目的同學(xué),但是你必須自己搭建過(guò)前端項(xiàng)目和后端項(xiàng)目,本文主要是介紹他們之間的互通,如果不知道這么搭建前端項(xiàng)目的同學(xué)可以先找別的blog看一下。
自己摸索了一下,可能會(huì)有一些問(wèn)題,也有可能有更好的實(shí)現(xiàn)方式,但這個(gè)demo主要是用來(lái)記錄自己搭建系統(tǒng),獨(dú)立完成前后端分離項(xiàng)目的過(guò)程,并且作為自己的畢業(yè)設(shè)計(jì)框架。所以有問(wèn)題的話歡迎提出,共同交流。源碼在github上,有需要的同學(xué)可以自己去取(地址在結(jié)尾)。

Demo功能描述

1.前端登陸頁(yè)面輸入http://localhost:8080/#/login會(huì)跳轉(zhuǎn)到前端登陸界面,輸入用戶名密碼后向后端 localhost:8888 發(fā)送驗(yàn)證請(qǐng)求
2.后臺(tái)接受輸入信息后,通過(guò)shiro認(rèn)證,向前臺(tái)返回認(rèn)證結(jié)果,密碼是通過(guò)md5加密的
3.登陸成功后,權(quán)限認(rèn)證,有些頁(yè)面只能管理員才能進(jìn)入,有些按鈕只能擁有某項(xiàng)權(quán)限的人才能看到,后臺(tái)有些接口只能被有權(quán)限的人訪問(wèn)。

Demo難點(diǎn)思考

前端工程在8080接口,發(fā)送的請(qǐng)求如何轉(zhuǎn)發(fā)到后臺(tái)8888接口

傳統(tǒng)的前后端未分離項(xiàng)目可以通過(guò)shiro標(biāo)簽在前臺(tái)進(jìn)行細(xì)粒度按鈕控制,獨(dú)立的前端vue項(xiàng)目如何做到這樣的控制

同上,前端項(xiàng)目如何實(shí)現(xiàn)帶權(quán)限的頁(yè)面跳轉(zhuǎn),因?yàn)樘D(zhuǎn)頁(yè)面的請(qǐng)求不會(huì)走后臺(tái),后臺(tái)只提供數(shù)據(jù)

解決思路:

這么解決上面的問(wèn)題?我這里的思路是(注*思路最重要,代碼只會(huì)貼關(guān)鍵代碼,全部代碼請(qǐng)上git上取):

8080端口請(qǐng)求8888端口本質(zhì)上是跨域問(wèn)題,兩種解決方式,1是在前端vue項(xiàng)目里面配置proxy,2是使用nginx反向代理,先采用第一種。nginx反向代理之后在介紹

登陸之后,后臺(tái)將roles和permissions信息傳給前臺(tái),前臺(tái)將持有登陸人的角色和權(quán)限信息(使用cookie和localstorage都可以,我結(jié)合了兩者使用)

使用router,綁定路由,訪問(wèn)權(quán)限綁定到對(duì)應(yīng)組件上,實(shí)現(xiàn)頁(yè)面級(jí)別的權(quán)限控制

使用指令,來(lái)控制細(xì)粒度級(jí)別的按鈕顯示等

Demo技術(shù)棧描述

1.前端技術(shù)棧

框架:vue+elementui+axios
語(yǔ)言:es6,js
環(huán)境:node8 + yarn
打包工具: webpack
開發(fā)工具:vscode

2.后端

框架:spring Boot多模塊+ maven + shiro + jpa + mysql8.0
開發(fā)工具:intellij idea
開發(fā)流程

1.后端開發(fā)流程

 ·搭建spring boot多模塊項(xiàng)目(本文不會(huì)介紹)
 ·創(chuàng)建shiro角色和權(quán)限的數(shù)據(jù)表
 ·集成shiro框架和md5加密
 ·開發(fā)登陸認(rèn)證接口

2.前端開發(fā)流程

·搭建前端運(yùn)行環(huán)境和webpack項(xiàng)目(本文不會(huì)介紹)
·開發(fā)登陸頁(yè)面組件
·跨域——來(lái)支持請(qǐng)求后端接口
·路由開發(fā),鉤子函數(shù)(頁(yè)面跳轉(zhuǎn)控制),cookieUtil開發(fā)(存儲(chǔ)后臺(tái)roles和permissions信息),自定義指令(前端細(xì)粒度控制)
·啟動(dòng)項(xiàng)目,測(cè)試登陸及權(quán)限驗(yàn)證
后端開發(fā)詳細(xì)流程

1.創(chuàng)建shiro角色和權(quán)限的數(shù)據(jù)表

結(jié)構(gòu)

用戶表(注意鹽的存在,為了md5加密用)

權(quán)限表

剩余兩張是用戶角色關(guān)聯(lián)表和角色權(quán)限關(guān)聯(lián)表,不展出了

2.集成shiro框架和md5加密

項(xiàng)目結(jié)構(gòu)(我們?cè)趕ecurity模塊中集成shiro)

maven包(全部的包看源碼,只貼核心的)

 
        
            org.apache.shiro
            shiro-spring
            ${shiro.version}
        
        
            org.apache.shiro
            shiro-core
            1.4.0
            compile
        

配置Realm類(shiro框架手動(dòng)配置的關(guān)鍵,用來(lái)登陸和權(quán)限認(rèn)證)

/**
 * Created by WJ on 2019/3/28 0028
 * 自定義權(quán)限匹配和密碼匹配
 */
public class MyShiroRealm extends AuthorizingRealm {
    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private UserRepository userRepository;

    @Resource
    private SysPermissionService sysPermissionService;

    @Resource
    private UserService userService;

    @Override
    public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("權(quán)限配置-->MyShiroRealm.doGetAuthorizationInfo()");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        User User = (User) principals.getPrimaryPrincipal();
        try {
            List roles = sysRoleService.selectRoleByUserId(User.getId());
            for (SysRole role : roles) {
                authorizationInfo.addRole(role.getRole());//角色存儲(chǔ)
            }
            //此處如果多個(gè)角色都擁有某項(xiàng)權(quán)限,bu會(huì)數(shù)據(jù)重復(fù),內(nèi)部用的是Set
            List sysPermissions = sysPermissionService.selectPermByRole(roles);
            for (SysPermission perm : sysPermissions) {
                authorizationInfo.addStringPermission(perm.getPermission());//權(quán)限存儲(chǔ)
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return authorizationInfo;
    }

    /*主要是用來(lái)進(jìn)行身份認(rèn)證的,也就是說(shuō)驗(yàn)證用戶輸入的賬號(hào)和密碼是否正確。*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
        //獲取用戶的輸入的賬號(hào).
        String username = (String) token.getPrincipal();
//       System.out.println(token.getCredentials());
        //通過(guò)username從數(shù)據(jù)庫(kù)中查找 User對(duì)象,如果找到,沒找到.
        //實(shí)際項(xiàng)目中,這里可以根據(jù)實(shí)際情況做緩存,如果不做,Shiro自己也是有時(shí)間間隔機(jī)制,2分鐘內(nèi)不會(huì)重復(fù)執(zhí)行該方法
        User user = userRepository.findByUsername(username).get();//*
        if (user == null) {
            return null;
        }

        if (user.getState() == 0) { //賬戶凍結(jié)
            throw new LockedAccountException();
        }

        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user, //用戶名
                user.getPassword(), //密碼
                ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }
}

shiroConfig(集成到spring框架中,攔截鏈及md5配置,md5配置完成之后,數(shù)據(jù)庫(kù)中存的應(yīng)該是加密過(guò)后的代碼,還有一些工具類請(qǐng)去源碼里面拿,這邊不貼)

@Configuration
public class ShiroConfig
{
    @Value("${sessionOutTime}")
    private String serverSessionTimeout;

    /**
     * 密碼校驗(yàn)規(guī)則HashedCredentialsMatcher,也就是密碼比對(duì)器
     * 這個(gè)類是為了對(duì)密碼進(jìn)行編碼的 ,
     * 防止密碼在數(shù)據(jù)庫(kù)里明碼保存 , 當(dāng)然在登陸認(rèn)證的時(shí)候 ,
     * 這個(gè)類也負(fù)責(zé)對(duì)form里輸入的密碼進(jìn)行編碼
     * 處理認(rèn)證匹配處理器:如果自定義需要實(shí)現(xiàn)繼承HashedCredentialsMatcher
     */
    @Bean("credentialsMatcher")
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //指定加密方式為MD5
        credentialsMatcher.setHashAlgorithmName("MD5");
        //加密次數(shù)
        credentialsMatcher.setHashIterations(1024);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }


    @Bean
    public FilterRegistrationBean delegatingFilterProxy() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        DelegatingFilterProxy proxy = new DelegatingFilterProxy();
        proxy.setTargetFilterLifecycle(true);
        proxy.setTargetBeanName("shiroFilter");
        filterRegistrationBean.setFilter(proxy);
        return filterRegistrationBean;
    }


    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必須設(shè)置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // setLoginUrl 如果不設(shè)置值,默認(rèn)會(huì)自動(dòng)尋找Web工程根目錄下的"/login.jsp"頁(yè)面 或 "/login" 映射
       // shiroFilterFactoryBean.setLoginUrl("/login");
        //設(shè)置成功跳轉(zhuǎn)的頁(yè)面
        //shiroFilterFactoryBean.setSuccessUrl("/index");
        // 設(shè)置無(wú)權(quán)限時(shí)跳轉(zhuǎn)的 url;
        //shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");

        // 設(shè)置攔截器
        Map filterChainDefinitionMap = new LinkedHashMap<>();

        //游客,開發(fā)權(quán)限
        //filterChainDefinitionMap.put("/**", "anon");
        filterChainDefinitionMap.put("/guest/**", "anon");
        //用戶,需要角色權(quán)限 “user”
        filterChainDefinitionMap.put("/user/**", "roles[user]");
        //管理員,需要角色權(quán)限 “admin”
        filterChainDefinitionMap.put("/admin/**", "roles[admin]");
        //開放登陸接口
        filterChainDefinitionMap.put("/api/ajaxLogin", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/loginUser", "anon");
        //其余接口一律攔截
        //主要這行代碼必須放在所有權(quán)限設(shè)置的最后,不然會(huì)導(dǎo)致所有 url 都被攔截
        filterChainDefinitionMap.put("/**", "authc");
        //配置shiro默認(rèn)登錄界面地址,前后端分離中登錄界面跳轉(zhuǎn)應(yīng)由前端路由控制,后臺(tái)僅返回json數(shù)據(jù)
        shiroFilterFactoryBean.setLoginUrl("/unauth");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        System.out.println("Shiro攔截器工廠類注入成功");
        return shiroFilterFactoryBean;
    }
    /*
    注入securityManager
     */
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //設(shè)置REALM
        securityManager.setRealm(customRealm());
        return securityManager;
    }
    /*
    自定義身份認(rèn)證realm
    必須寫上這個(gè)類,并加上@Bean注解,目的是注入CustomRealm
    否則會(huì)影響CustomRealm類中其他類的依賴注入
     */
    @Bean
    public MyShiroRealm customRealm(){
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());// 將md5密碼比對(duì)器傳給realm
        return  myShiroRealm;
    }
    /*
    開啟注解支持
     */
    @Bean
    //@DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public FilterRegistrationBean shiroSessionFilterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new ShiroSessionFilter());
        filterRegistrationBean.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
        filterRegistrationBean.setEnabled(true);
        filterRegistrationBean.addUrlPatterns("/*");
        Map initParameters = new HashMap<>();
        initParameters.put("serverSessionTimeout", serverSessionTimeout);
        initParameters.put("excludes", "/favicon.ico,/images/*,/js/*,/css/*,/static/*,/upload/*");
        filterRegistrationBean.setInitParameters(initParameters);
        return filterRegistrationBean;
    }

    /*@Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }*/

}

md5加密Test代碼,將結(jié)果存到數(shù)據(jù)庫(kù),salt值是 用戶名 + "salt"

 @Test
    public void md5Test() {
        String hashAlgorithName = "MD5";
        String password = "123456";
        int hashIterations = 1024;
        ByteSource byteSource = ByteSource.Util.bytes("wujiesalt");
        Object obj = new SimpleHash(hashAlgorithName, password, byteSource, hashIterations);
        System.out.println("加密之后的密碼" + obj);
    }

開發(fā)登陸接口(注意這個(gè)接口是在shiroconfig中配置開放的)

@Controller
public class ShiroController {
   @Resource
   private LoginService loginService;
    /**
     * 登錄方法
     * @param userInfo
     * @return
     */
    @RequestMapping(value = "/api/ajaxLogin", method = RequestMethod.POST, produces = "application/json; charset=UTF-8")
    @ResponseBody
    public Result ajaxLogin(@RequestBody User userInfo) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userInfo.getUsername(), userInfo.getPassword());

        try {
            subject.login(token);
            LoginInfo loginInfo = loginService.getLoginInfo(userInfo.getUsername());
            return ResultFactory.buildSuccessResult(loginInfo);// 將用戶的角色和權(quán)限發(fā)送到前臺(tái)
        } catch (IncorrectCredentialsException e) {
            return ResultFactory.buildFailResult("密碼錯(cuò)誤");
        } catch (LockedAccountException e) {
            return ResultFactory.buildFailResult("登錄失敗,該用戶已被凍結(jié)");
        } catch (AuthenticationException e) {
            return ResultFactory.buildFailResult("該用戶不存在");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ResultFactory.buildFailResult("登陸失敗");
    }

    /**
     * 未登錄,shiro應(yīng)重定向到登錄界面,此處返回未登錄狀態(tài)信息由前端控制跳轉(zhuǎn)頁(yè)面
     * @return
     */
    @RequestMapping(value = "/unauth")
    @ResponseBody
    public Object unauth() {
        Map map = new HashMap();
        map.put("code", "1000000");
        map.put("msg", "未登錄");
        return map;
    }
}
@Service
public class LoginService {
    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private UserRepository userRepository;

    @Resource
    private SysPermissionService sysPermissionService;

    public LoginInfo getLoginInfo(String username) {
        User user = userRepository.findByUsername(username).get();

        List roles = sysRoleService.selectRoleByUserId(user.getId());

        Set roleList = new HashSet<>();
        Set permissionList = new HashSet<>();
        for (SysRole role : roles) {
            roleList.add(role.getRole());//角色存儲(chǔ)
        }
        //此處如果多個(gè)角色都擁有某項(xiàng)權(quán)限,bu會(huì)數(shù)據(jù)重復(fù),內(nèi)部用的是Set
        List sysPermissions = sysPermissionService.selectPermByRole(roles);
        for (SysPermission perm : sysPermissions) {
            permissionList.add(perm.getPermission());//權(quán)限存儲(chǔ)
        }

        return  new LoginInfo(roleList,permissionList);
    }
}
請(qǐng)輸入代碼/**
 * Created by WJ on 2019/3/26 0026
 */
public class ResultFactory {
    public static Result buildSuccessResult(LoginInfo data) {
        return buidResult(ResultCode.SUCCESS, "成功", data);
    }

    public static Result buildFailResult(String message) {
        return buidResult(ResultCode.FAIL, message, null);
    }

    public static Result buidResult(ResultCode resultCode, String message, LoginInfo data) {
        return buidResult(resultCode.code, message, data);
    }

    public static Result buidResult(int resultCode, String message, LoginInfo data) {
        return new Result(resultCode, message, data);
    }
}
public class Result {
    /**
     * 響應(yīng)狀態(tài)碼
     */
    private int code;
    /**
     * 響應(yīng)提示信息
     */
    private String message;
    /**
     * 響應(yīng)結(jié)果對(duì)象
     */
    private LoginInfo loginInfo;

    public Result(int code, String message, LoginInfo loginInfo) {
        this.code = code;
        this.message = message;
        this.loginInfo = loginInfo;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public LoginInfo getLoginInfo() {
        return loginInfo;
    }

    public void setLoginInfo(LoginInfo loginInfo) {
        this.loginInfo = loginInfo;
    }
}

好啦!到這里后臺(tái)的工作基本完成了,現(xiàn)在去開發(fā)前臺(tái)

前臺(tái)開發(fā)流程

登陸頁(yè)面的開發(fā)



cookie.js,用來(lái)設(shè)置cookie,存儲(chǔ)后臺(tái)傳過(guò)來(lái)的數(shù)據(jù)

export function setCookie(key,value) {
    var exdate = new Date();//獲取時(shí)間
    exdate.setTime(exdate.getTime() + 24 * 60 *60); //保存的天數(shù),一天
    //字符串拼接cookie
    window.document.cookie = key + "=" + value + ";path=/;expires=" + exdate.toGMTString();
}

//讀取cookie
export function getCookie(param) {
    var c_param = "";
    if (document.cookie.length > 0) {
        console.log("原document cookie: " + document.cookie);
        var arr = document.cookie.split("; "); //獲取key value數(shù)組
        for (var i = 0; i < arr.length; i++) {
            var arr2 = arr[i].split("="); //獲取該key 下面的 value數(shù)組
            if(arr2[0] == param) {
                c_param = arr2[1];

            }
        }

        return c_param;
    }
}

function padLeftZero (str) {
    return ("00" + str).substr(str.length);
  };

請(qǐng)求成功后,使用鉤子函數(shù)結(jié)合router路由跳轉(zhuǎn)頁(yè)面,(每次跳轉(zhuǎn)頁(yè)面都會(huì)走鉤子函數(shù),配合路由配置,而且這時(shí)候我們已經(jīng)拿到了當(dāng)前用戶的角色和權(quán)限,結(jié)合實(shí)現(xiàn)頁(yè)面權(quán)限跳轉(zhuǎn)),以下為main.js

import axios from "axios";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css"; // 默認(rèn)主題
// import "../static/css/theme-green/index.css";       // 淺綠色主題
import "./assets/css/icon.css";
import "./components/common/directives";
import "babel-polyfill";
import {setCookie,getCookie} from "./assets/js/cookie";

Vue.config.productionTip = false
Vue.use(ElementUI, {
    size: "small"
});
axios.default.baseURL = "https://localhost:8888"
Vue.prototype.$axios = axios;

//使用鉤子函數(shù)對(duì)路由進(jìn)行權(quán)限跳轉(zhuǎn)
router.beforeEach((to, from, next) => {
    const roles = localStorage.getItem("roles");
    const permissions = localStorage.getItem("permissions");
    //這邊可以用match()來(lái)判斷所有需要權(quán)限的路徑,to.matched.some(item => return item.meta.loginRequire)
    let cookieroles = getCookie("roles");
    console.log("cookie" + cookieroles);
    if (!cookieroles && to.path !== "/login") { // cookie中有登陸用戶信息跳轉(zhuǎn)頁(yè)面,否則到登陸頁(yè)面
        next("/login");
    } else if (to.meta.permission) {// 如果該頁(yè)面配置了權(quán)限屬性(自定義permission)
        // 如果是管理員權(quán)限則可進(jìn)入
        roles.indexOf("admin") > -1 ? next() : next("/403");
    } else {
        // 簡(jiǎn)單的判斷IE10及以下不進(jìn)入富文本編輯器,該組件不兼容
        if (navigator.userAgent.indexOf("MSIE") > -1 && to.path === "/editor") {
            Vue.prototype.$alert("vue-quill-editor組件不兼容IE10及以下瀏覽器,請(qǐng)使用更高版本的瀏覽器查看", "瀏覽器不兼容通知", {
                confirmButtonText: "確定"
            });
        } else {
            next();
        }
    }
})
// 在管理員頁(yè)面配置 permission = true
import Vue from "vue";
import Router from "vue-router";

Vue.use(Router);

export default new Router({
    routes: [
        {
            path: "/",
            redirect: "/dashboard"
        },
        {
            path: "/",
            component: resolve => require(["../components/common/Home.vue"], resolve),
            meta: { title: "自述文件" },
            children:[
                {
                    path: "/dashboard",
                    component: resolve => require(["../components/page/Dashboard.vue"], resolve),
                    meta: { title: "系統(tǒng)首頁(yè)" }
                },
                {
                    path: "/icon",
                    component: resolve => require(["../components/page/Icon.vue"], resolve),
                    meta: { title: "自定義圖標(biāo)" }
                },
                {
                    path: "/table",
                    component: resolve => require(["../components/page/BaseTable.vue"], resolve),
                    meta: { title: "基礎(chǔ)表格" }
                },
                {
                    path: "/tabs",
                    component: resolve => require(["../components/page/Tabs.vue"], resolve),
                    meta: { title: "tab選項(xiàng)卡" }
                },
                {
                    path: "/form",
                    component: resolve => require(["../components/page/BaseForm.vue"], resolve),
                    meta: { title: "基本表單" }
                },
                {
                    // 富文本編輯器組件
                    path: "/editor",
                    component: resolve => require(["../components/page/VueEditor.vue"], resolve),
                    meta: { title: "富文本編輯器" }
                },
                {
                    // markdown組件
                    path: "/markdown",
                    component: resolve => require(["../components/page/Markdown.vue"], resolve),
                    meta: { title: "markdown編輯器" }    
                },
                {
                    // 圖片上傳組件
                    path: "/upload",
                    component: resolve => require(["../components/page/Upload.vue"], resolve),
                    meta: { title: "文件上傳" }   
                },
                {
                    // vue-schart組件
                    path: "/charts",
                    component: resolve => require(["../components/page/BaseCharts.vue"], resolve),
                    meta: { title: "schart圖表" }
                },
                {
                    // 拖拽列表組件
                    path: "/drag",
                    component: resolve => require(["../components/page/DragList.vue"], resolve),
                    meta: { title: "拖拽列表" }
                },
                {
                    // 拖拽Dialog組件
                    path: "/dialog",
                    component: resolve => require(["../components/page/DragDialog.vue"], resolve),
                    meta: { title: "拖拽彈框" }
                },
                {
                    // 權(quán)限頁(yè)面
                    path: "/permission",
                    component: resolve => require(["../components/page/Permission.vue"], resolve),
                    meta: { title: "權(quán)限測(cè)試", permission: true } // 配合鉤子函數(shù)實(shí)現(xiàn)權(quán)限認(rèn)證
                },
                {
                    path: "/404",
                    component: resolve => require(["../components/page/404.vue"], resolve),
                    meta: { title: "404" }
                },
                {
                    path: "/403",
                    component: resolve => require(["../components/page/403.vue"], resolve),
                    meta: { title: "403" }
                }
            ]
        },
        {
            path: "/login",
            component: resolve => require(["../components/page/Login.vue"], resolve)
        },
        {
            path: "*",
            redirect: "/404"
        }
    ]
})

自定義指令實(shí)現(xiàn)細(xì)粒度的按鈕顯示等控制(例:如果我們想控制某個(gè)角色或者擁有某項(xiàng)權(quán)限才能看到編輯按鈕)

Vue.directive("hasAuthorization",{
    bind: (el) => {
        const roles = localStorage.getItem("roles");
        console.log(roles);
        if(!(localStorage.getItem("roles").indexOf("admin") > -1)){
            el.setAttribute("style","display:none")
        }
    }
})
//在按鈕中設(shè)置指令,這樣只有管理員才能看到這個(gè)按鈕并使用,配置權(quán)限同理
編輯

配置proxy來(lái)支持跨域,向后臺(tái)請(qǐng)求登陸和數(shù)據(jù)

// 在vue.config.js中配置profxy
module.exports = {
    baseUrl: "./",
    productionSourceMap: false,
    devServer: {
        proxy: {
            "/api":{
                target: "http://127.0.0.1:8888",// 這里設(shè)置調(diào)用的域名和端口號(hào),需要http,注意不是https!
                changeOrigin: true,
                pathRewrite: {
                    "^/api": "/api" //這邊如果為空的話,那么發(fā)送到后端的請(qǐng)求是沒有/api這個(gè)前綴的
                }
            }
        }
    }
}

//還要在man.js中配置axios
axios.default.baseURL = "https://localhost:8888"
Vue.prototype.$axios = axios;
運(yùn)行效果

管理員賬號(hào)登入

非管理員用戶

總結(jié)

與傳統(tǒng)的項(xiàng)目最大的區(qū)別就是,我們使用了vue router控制頁(yè)面跳轉(zhuǎn),使用指令來(lái)細(xì)粒度控制,使用了cookie和localstorage(其實(shí)選擇一個(gè)來(lái)記錄就可以了,這邊有小Bug待解決)記錄了用戶信息。

主要提供了這樣一個(gè)思路,設(shè)計(jì)到vue中不懂的知識(shí)點(diǎn)可以直接取官網(wǎng)上面找,比我在這邊講清楚

后端地址:git@github.com:Attzsthl/land-mange.git前端地址:git@github.com:Attzsthl/land-mange-fronted.git

歡迎交流,有問(wèn)題和不清楚的地方我會(huì)解答,謝謝觀看!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/77578.html

相關(guān)文章

  • 兩年了,我寫了這些干貨!

    摘要:開公眾號(hào)差不多兩年了,有不少原創(chuàng)教程,當(dāng)原創(chuàng)越來(lái)越多時(shí),大家搜索起來(lái)就很不方便,因此做了一個(gè)索引幫助大家快速找到需要的文章系列處理登錄請(qǐng)求前后端分離一使用完美處理權(quán)限問(wèn)題前后端分離二使用完美處理權(quán)限問(wèn)題前后端分離三中密碼加鹽與中異常統(tǒng)一處理 開公眾號(hào)差不多兩年了,有不少原創(chuàng)教程,當(dāng)原創(chuàng)越來(lái)越多時(shí),大家搜索起來(lái)就很不方便,因此做了一個(gè)索引幫助大家快速找到需要的文章! Spring Boo...

    huayeluoliuhen 評(píng)論0 收藏0
  • springboot整合shiro使用shiro-spring-boot-web-starter

    摘要:此文章僅僅說(shuō)明在整合時(shí)的一些坑并不是教程增加依賴集成依賴配置三個(gè)必須的用于授權(quán)和登錄創(chuàng)建自己的實(shí)例用于實(shí)現(xiàn)權(quán)限三種方式實(shí)現(xiàn)定義權(quán)限路徑第一種使用角色名定義第二種使用權(quán)限定義第三種使用接口的自定義配置此處配置之后需要在對(duì)應(yīng)的 此文章僅僅說(shuō)明在springboot整合shiro時(shí)的一些坑,并不是教程 增加依賴 org.apache.shiro shiro-spring-...

    sevi_stuo 評(píng)論0 收藏0
  • Spring Boot 整合 Shiro

    摘要:雖然,直接用和進(jìn)行全家桶式的合作是最好不過(guò)的,但現(xiàn)實(shí)總是欺負(fù)我們這些沒辦法決定架構(gòu)類型的娃子。并非按輸入順序。遍歷時(shí)只能全部輸出,而沒有順序。設(shè)想以下,若全局劫持在最前面,那么只要在襠下的,都早早被劫持了。底層是數(shù)組加單項(xiàng)鏈表加雙向鏈表。 雖然,直接用Spring Security和SpringBoot 進(jìn)行全家桶式的合作是最好不過(guò)的,但現(xiàn)實(shí)總是欺負(fù)我們這些沒辦法決定架構(gòu)類型的娃子。 Apa...

    newsning 評(píng)論0 收藏0
  • Spring Security

    摘要:框架具有輕便,開源的優(yōu)點(diǎn),所以本譯見構(gòu)建用戶管理微服務(wù)五使用令牌和來(lái)實(shí)現(xiàn)身份驗(yàn)證往期譯見系列文章在賬號(hào)分享中持續(xù)連載,敬請(qǐng)查看在往期譯見系列的文章中,我們已經(jīng)建立了業(yè)務(wù)邏輯數(shù)據(jù)訪問(wèn)層和前端控制器但是忽略了對(duì)身份進(jìn)行驗(yàn)證。 重拾后端之Spring Boot(四):使用JWT和Spring Security保護(hù)REST API 重拾后端之Spring Boot(一):REST API的搭建...

    keelii 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<