ruoyi cloud集成casdoor

        之前写过一篇关于ruoyi cloud集成cas的但是使用的apereo的单点登录,该应用的文档都是英文文档,尝试一下集成casdoor,其官方文档比较详细。

考虑到有些小伙伴上git不方便,需要用到的代码和Windows工具,都在这了        

1、环境搭建

    我沿用了之前的服务器,所以在官网下载Go 1.9的windows安装包

    下载msi,傻瓜式安装,cmd输入go version,出现版本号,收工

     后两项就不写了,网上太多

2、casdoor部署

创建文件夹,右键git bash

 git clone https://github.com/casdoor/casdoor.git

下载完成代码后,进入casdoor-master文件夹,修改conf,修改app.conf文件,datasourcename:数据库的用户名,密码,地址,dbName:数据库名

appname = casdoor
httpport = 8000
runmode = dev
SessionOn = true
copyrequestbody = true
driverName = mysql
dataSourceName = root:123456@tcp(localhost:3306)/
dbName = casdoor
tableNamePrefix =
showSql = false
redisEndpoint =
defaultStorageProvider =
isCloudIntranet = false
authState = "casdoor"
socks5Proxy = "127.0.0.1:10808"
verificationCodeTimeout = 10
initScore = 2000
logPostOnly = true
origin = "https://door.casdoor.com"
staticBaseUrl = "https://cdn.casbin.org"

进入cmd,切换国内代理

go env -w GOPROXY=https://goproxy.cn

使用命令运行后端

go run main.go

进入web文件夹,cmd,下载yarn

npm install --global yarn

验证yarn是否安装完成

yarn --version

安装前端依赖

yarn install

前端运行

yarn start

3配置casdoor

1、新建组织,将密码类型呢改成bcrypt,并开启软删除

2、新建同步器,配置数据库密码,修改表列 

3、保存和同步,查看若依的用户是否存在

4、新建应用和证书,在新建的应用中,选择新创建的证书,在重定向urls内添加

http://localhost:81/login

4修改若依前端

1、安装vue-sdk

npm i casdoor-vue-sdk --save

2、执行指令

npx vue-demi-fix

3、修改main.js


//新增
import Casdoor from 'casdoor-vue-sdk'
import VueCompositionAPI from '@vue/composition-api'
const config = {
  serverUrl: "你的casdoor路径",
  clientId: "客户端id",
  organizationName: "组织名称",
  appName: "应用名称",
  redirectPath: "/login(重定向回来的路径)",
};
Vue.use(VueCompositionAPI)
Vue.use(Casdoor,config)

//修改
new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
}).$mount('#app')

4、修改login.vue(直接替换)

<template>
  <div class="login">
    <el-form ref="loginForm"  class="login-form">
      <h3 class="title">若依后台管理系统</h3>

    </el-form>
    <!--  底部  -->
    <div class="el-login-footer">
      <span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
    </div>
  </div>
</template>

<script>
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from '@/utils/jsencrypt'

export default {
  name: "Login",
  data() {
    return {
      codeUrl: "",
      loginForm: {
        code: "",
        state: ""
      },

      loading: false,
      // 验证码开关
      captchaEnabled: false,
      // 注册开关
      register: true,
      redirect: undefined
    };
  },
  watch: {
    $route: {
      handler: function(route) {
        this.redirect = route.query && route.query.redirect;
      },
      immediate: true
    }
  },
  created() {
    /*this.getCode();
    this.getCookie();*/

      let url = window.document.location.href//get url
      let u = new URL(url);
      this.loginForm.code = u.searchParams.get('code')//get code and state
      this.loginForm.state = u.searchParams.get('state')
      if(this.loginForm.code!=null&&this.loginForm.state!=null){//if code and state is null, execute handleLogin
        this.handleLogin()
      }else{
        window.location.href = this.getSigninUrl();
      }

  },
  methods: {
    handleLogin() {
      console.log("进入handleLogin",this.loginForm);
      this.$store.dispatch("Login",this.loginForm).then(()=>{
        this.$router.push({path:this.redirect || "/"}).catch(()=>{});
      }).catch(()=>{
        this.loading = false;
      })
    }
  }
};
</script>

<style rel="stylesheet/scss" lang="scss">
.login {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  background-image: url("../assets/images/login-background.jpg");
  background-size: cover;
}
.title {
  margin: 0px auto 30px auto;
  text-align: center;
  color: #707070;
}

.login-form {
  border-radius: 6px;
  background: #ffffff;
  width: 400px;
  padding: 25px 25px 5px 25px;
  .el-input {
    height: 38px;
    input {
      height: 38px;
    }
  }
  .input-icon {
    height: 39px;
    width: 14px;
    margin-left: 2px;
  }
}
.login-tip {
  font-size: 13px;
  text-align: center;
  color: #bfbfbf;
}
.login-code {
  width: 33%;
  height: 38px;
  float: right;
  img {
    cursor: pointer;
    vertical-align: middle;
  }
}
.el-login-footer {
  height: 40px;
  line-height: 40px;
  position: fixed;
  bottom: 0;
  width: 100%;
  text-align: center;
  color: #fff;
  font-family: Arial;
  font-size: 12px;
  letter-spacing: 1px;
}
.login-code-img {
  height: 38px;
}
</style>

5、修改user.js的login方法

Login({ commit }, userInfo) {
      const code = userInfo.code
      const state = userInfo.state
      return new Promise((resolve, reject) => {
        login(code, state).then(res => {
          let data = res.data
          setToken(data.access_token)
          commit('SET_TOKEN', data.access_token)
          setExpiresIn(data.expires_in)
          commit('SET_EXPIRES_IN', data.expires_in)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

6、修改api下面的login.js

export function login(code,state) {
  return request({
    url: '/auth/login',
    headers: {
      isToken: false
    },
    method: 'post',
    data: { code,state }
  })
}

可以尝试运行,是否会跳转,是否能返回code和state

5、修改若依后端

1、导入依赖

<dependency>
            <groupId>org.casbin</groupId>
            <artifactId>casdoor-spring-boot-starter</artifactId>
            <version>1.2.0</version>
</dependency>

2、新建实体CodeBody

package com.ruoyi.auth.form;


public class CodeBody {
    private String code;
    private String state;

    public String getCode() {
        return code;
    }

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

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    @Override
    public String toString() {
        return "CodeBody{" +
                "code='" + code + '\'' +
                ", state='" + state + '\'' +
                '}';
    }
}

3、修改tokenController,login方法

    @PostMapping("login")
    public R<?> callback(@RequestBody CodeBody code) {//we should define a CodeBody entity which have code and state
        String token = casdoorAuthService.getOAuthToken(code.getCode(), code.getState());
        CasdoorUser casdoorUser = casdoorAuthService.parseJwtToken(token);
        if(casdoorUser.getName()!=null){
            String casdoorUserName = casdoorUser.getName();
            if(sysLoginService.getUserByCasdoorName(casdoorUserName)==null){//if database haven't this user
                // add this user into database
                sysLoginService.casdoorRegister(casdoorUserName);
            }
        }
        LoginUser userInfo = sysLoginService.casdoorLogin(casdoorUser.getName());//get this user's information by database
        return R.ok(tokenService.createToken(userInfo));
    }

4、sysloginService新增三个方法

public LoginUser casdoorLogin(String username){
        // execute user
        R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode())
        {
            throw new ServiceException(userResult.getMsg());
        }

        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "this user is not exist");
            throw new ServiceException("user:" + username + " is not exist");
        }
        LoginUser userInfo = userResult.getData();
        SysUser user = userResult.getData().getSysUser();
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "sorry, your account was deleted");
            throw new ServiceException("sorry, your account:" + username + " was deleted");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "your account is disabled, you can contact admin ");
            throw new ServiceException("sorry, your account:" + username + " is disabled");
        }
        recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "login successfully");
        return userInfo;
    }
    public String getUserByCasdoorName(String casdoorUsername){
        R<LoginUser> userResult = remoteUserService.getUserInfo(casdoorUsername, SecurityConstants.INNER);
        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
        {
            //if this user is not in RuoYi-Cloud database and casdoor have this user, we should create this user in database
            return null;
        }
        String username = userResult.getData().getSysUser().getUserName();
        return username;
    }
    public void casdoorRegister(String username){
        if (StringUtils.isAnyBlank(username))
        {
            throw new ServiceException("User must fill in");
        }
        SysUser sysUser = new SysUser();
        sysUser.setUserName(username);
        sysUser.setNickName(username);
        R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);
        System.out.println(registerResult);
        if (R.FAIL == registerResult.getCode())
        {
            throw new ServiceException(registerResult.getMsg());
        }
        recordLogService.recordLogininfor(username, Constants.REGISTER, "register successfully");
    }

5、bootstrap.yml内新增casdoor配置

server: 
  port: 36000
casdoor:
  endpoint: casdoor地址
  client-id: 客户端id
  client-secret: 客户端密钥
  certificate: 证书名称
  jwtPublicKey: 证书公钥,注意拷下来的公钥,每一行结尾加\n\,如"-----BEGIN CERTIFICATE-----\n\
  MIIE2TCCAsGgAwIBAgIDAeJAMA0GCSqGSIb3DQEBCwUAMCYxDjAMBgNVBAoTBWFk\n\
 .
 .
 .
  teANTdYzr6IIZiweG1/vvAXIk4HfjyVtOvxYAa6tfe0hpXDhCcqsO2ekpm0H\n\
  -----END CERTIFICATE-----"
  organization-name: 组织名称
  application-name: 应用名称

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值