RuoYi
Casdoor يمكن دمجها بسهولة مع RuoYi-cloud.
الخطوة 1: نشر Casdoor
أولاً، نشر Casdoor.
يمكنك الرجوع إلى الوثائق الرسمية لـ Casdoor لـ تثبيت الخادم.
بعد النشر الناجح، تأكد من الآتي:
- خادم Casdoor يعمل على http://localhost:8000.
- افتح متصفحك المفضل وزر http://localhost:7001 للوصول إلى صفحة تسجيل الدخول Casdoor.
- اختبر وظيفة تسجيل الدخول بإدخال
admin
و123
.
بعد ذلك، يمكنك تنفيذ صفحة تسجيل دخول تعتمد على Casdoor في تطبيقك الخاص باتباع هذه الخطوات.
الخطوة 2: تكوين Casdoor
لتكوين Casdoor، يرجى اتباع الخطوات التالية:
افتح Casdoor في متصفح بالنقر هنا. يُنصح باستخدام متصفح مختلف عن متصفح التطوير الخاص بك.
قم بتكوين منظمة، وتطبيق، والمزامن في Casdoor. يمكنك العثور على تعليمات مفصلة حول كيفية القيام بذلك هنا.
إليك بعض النقاط الإضافية التي يجب وضعها في الاعتبار:
عند تحرير المزامن، تأكد من التحقق من أعمدة الجدول: .
عند تحرير المنظمة، تأكد من اختيار نوع كلمة المرور الصحيح: .
وأخيرًا، تأكد من تمكين الحذف الناعم.
يرجى التأكد من اتباع هذه التعليمات بعناية لتكوين Casdoor بشكل صحيح.
الخطوة 3. أعد تشكيل واجهة المستخدم الأمامية
3.1 الانتقال إلى صفحة تسجيل الدخول Casdoor
يمكننا استخدام SDK للواجهة الأمامية، مع أخذ vue-sdk كمثال هنا. بعد تهيئة vue-sdk، يمكنك الحصول على عنوان URL لصفحة تسجيل الدخول Casdoor باستخدام وظيفة getSigninUrl().
يمكنك ربطه بالطريقة التي تفضلها، ولا تتردد في حذف أي كود أصلي من Ruoyi-Cloud غير ضروري، مثل الحساب الأصلي و el-input لكلمة المرور.
3.2 قبول الرمز والحالة المرسلة من Casdoor
بعد تسجيل الدخول بنجاح من خلال Casdoor، يرسل Casdoor الرمز والحالة إلى الصفحة التي قمنا بإعدادها. يمكننا استرجاع الرمز والحالة باستخدام وظيفة create().
created() {
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 are not null, execute handleLogin
this.handleLogin();
}
}
بالنسبة لـ RuoYi-Cloud، نقوم ببساطة بتعديل طريقته الأصلية لإرسال الحساب وكلمة المرور لإرسال الرمز والحالة بدلاً من ذلك. لذلك، التغيير فقط في ما يتم إرساله إلى الخلفية، بالنسبة لتسجيل الدخول الأصلي.
الخطوة 4: إعادة تشكيل الخلفية
4.1 قبول الرمز والحالة المرسلة من الواجهة الأمامية
@PostMapping("login")
public R<?> callback(@RequestBody CodeBody code) {
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) {
sysLoginService.casdoorRegister(casdoorUserName); // Add this user to the database if they don't exist
}
}
LoginUser userInfo = sysLoginService.casdoorLogin(casdoorUser.getName()); // Get the user's information from the database
return R.ok(tokenService.createToken(userInfo));
}
في هذه الطريقة، نحن نستخدم طريقة casdoor-SpringBoot-sdk ونقوم بتعديلات طفيفة على طريقة RuoYi-Cloud.
على سبيل المثال، طريقة RuoYi-Cloud الأصلية تسجل حسابًا بكلمة مرور. لقد غيرتها لتسجيل حساب باستخدام طريقة casdoorRegister
.
لقد أضفت أيضًا طريقة getUserByCasdoorName
للتحقق مما إذا كان الحساب موجودًا، وغيرت طريقة executeUserInfo
إلى executeWithAccount
لتعكس هذا التغيير.
هذا تعديل سهل، حيث نحتاج فقط إلى إزالة الجزء الذي يتحقق من كلمة المرور.
الخطوة 5: الملخص
5.1 الواجهة الأمامية
- يجب إزالة صفحات تسجيل الدخول والتسجيل الحالية.
- بالإضافة إلى ذلك، تحتاج الواجهة الأمامية إلى قبول معلمات الرمز والحالة وإرسالها إلى الخلفية.
5.2 الخلفية
لقد تم تنفيذ وظيفة تسجيل الدخول والتسجيل بشكل جيد بالفعل في الخلفية لـ RuoYi. نحن بحاجة فقط إلى إجراء بعض التعديلات الطفيفة، مما يجعل العملية مريحة للغاية.
الخطوة 6: خطوات مفصلة
قم بنشر وتكوين Casdoor. تأكد من اختيار نوع كلمة المرور bcrypt للمنظمة، حيث يستخدم RuoYi-Cloud أيضًا bcrypt لكلمات المرور.
استخدم مزامني Casdoor لنسخ مستخدمي قاعدة البيانات إلى منظمة Casdoor الخاصة بك. سيؤدي هذا إلى استيراد الحسابات الأصلية إلى Casdoor.
بعد نشر Casdoor، قم بإجراء تغييرات على الواجهة الأمامية. قم بتعطيل رمز التحقق RuoYi.
لاحظ أنه يجب تعطيل كلمة التحقق RuoYi-Cloud في Nacos مرة أخرى. أيضًا، يجب تمكين وظيفة التسجيل RuoYi-Cloud من خلال تعيين
sys.account.registerUser
إلىtrue
.أضف زرًا للمستخدمين لتسجيل الدخول باستخدام Casdoor، وقم بتعديل بيانات
loginForm
.هنا، لقد كتبت الرابط، ولكن يمكنك الحصول عليه باستخدام Casdoor-Vue-SDK أو Casdoor-SpringBoot-SDK.
بما أننا لم نعد نستخدم طريقة تسجيل الدخول الأصلية، احذف ملفات تعريف الارتباط وطرق التحقق.
يجب أن تبدو الوظيفة الجديدة
created
كما يلي:created() {
let url = window.document.location.href; // Get the URL
let u = new URL(url);
this.loginForm.code = u.searchParams.get('code'); // Get the code and state
this.loginForm.state = u.searchParams.get('state');
if (this.loginForm.code != null && this.loginForm.state != null) { // If code and state are not null, execute handleLogin
this.handleLogin();
}
}في الواقع، نحن بحاجة فقط إلى تغيير المعامل الذي نرسله إلى الخلفية وحذف الوظائف غير الضرورية. لا توجد تغييرات أخرى ضرورية.
استورد الاعتماد المطلوب في الخلفية.
pom.xml<dependency>
<groupId>org.casbin</groupId>
<artifactId>casdoor-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>تحتاج أيضًا إلى تكوين Casdoor في ملف الموارد.
حدد وظيفة الرد كوظيفة إعادة التوجيه. قم بإجراء تغييرات على بعض الطرق في
sysLoginService
. احذف خطوة التحقق من كلمة المرور لأنها لم تعد ضرورية.@PostMapping("login")
public R<?> callback(@RequestBody CodeBody code) {
// Define a CodeBody entity with 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 the user is not in the RuoYi-Cloud database but exists in Casdoor, create the user in the database
sysLoginService.casdoorRegister(casdoorUserName);
}
}
LoginUser userInfo = sysLoginService.casdoorLogin(casdoorUser.getName());
// Get the user's information from the database
return R.ok(tokenService.createToken(userInfo));
}أضف طرق جديدة إلى
SysLoginService
.public LoginUser casdoorLogin(String username) {
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
// Execute the user
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 does not exist");
throw new ServiceException("User " + username + " does 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 has been deleted");
throw new ServiceException("Sorry, your account " + username + " has been deleted");
}
if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "Your account is disabled. Please contact the administrator");
throw new ServiceException("Sorry, your account " + username + " is disabled");
}
recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "Login successful");
return userInfo;
}public String getUserByCasdoorName(String casdoorUsername) {
R<LoginUser> userResult = remoteUserService.getUserInfo(casdoorUsername, SecurityConstants.INNER);
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
// If the user is not in the RuoYi-Cloud database but exists in Casdoor, create the user in the 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 provide a username");
}
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, "Registration successful");
}