فلتر الأمان Spring Security مع تكامل OIDC لـ Casdoor
Casdoor هو مزود هوية مفتوح المصدر يدعم OIDC وبروتوكولات متنوعة أخرى. في هذا المقال، سنرى كيفية دمج Casdoor مع تطبيقك باستخدام فلتر الأمان Spring Security و OIDC.
الخطوة 1: نشر Casdoor
أولاً، تحتاج إلى نشر خادم Casdoor. راجع التوثيق الرسمي للحصول على تعليمات تثبيت الخادم. بعد النشر الناجح، تأكد من أن:
- خادم Casdoor يعمل على http://localhost:8000.
- يمكنك رؤية صفحة تسجيل الدخول إلى Casdoor على http://localhost:7001.
- يمكنك اختبار وظيفة تسجيل الدخول بتسجيل الدخول باستخدام بيانات الاعتماد
admin
و123
.
بعد التحقق من هذه الخطوات، اتبع الخطوات أدناه لدمج Casdoor مع تطبيقك.
الخطوة 2: تكوين تطبيق Casdoor
- أنشئ تطبيق Casdoor جديد أو استخدم واحدًا موجودًا.
- أضف عنوان URL الخاص بإعادة التوجيه. يمكنك العثور على مزيد من المعلومات حول الحصول على عنوان URL لإعادة التوجيه في القسم التالي.
- احصل على
Certificate
الخاص بك في صفحة تحرير الشهادة. - أضف المزود والإعدادات الأخرى حسب الحاجة.
يمكنك الحصول على القيم لـ Application Name
، Organization Name
، Redirect URL
، Client ID
، Client Secret
، و Certificate
في صفحة إعدادات التطبيق. سنستخدمها في الخطوة التالية.
الخطوة 3: تكوين Spring Security
يمكنك تخصيص إعدادات فلاتر Spring Security لمعالجة الرموز:
تأكد من استبدال قيم التكوين بقيم خاصة بك من مثيل Casdoor الخاص بك، خاصة <Client ID>
والقيم الأخرى.
server:
port: 8080
casdoor:
endpoint: http://CASDOOR_HOSTNAME:8000
client-id: <Client ID>
client-secret: <Client Secret>
certificate: <Certificate>
organization-name: <Organization Name>
application-name: <Application Name>
redirect-url: http://FRONTEND_HOSTNAME/callback
بالنسبة لتطبيقات الواجهة الأمامية، القيمة الافتراضية لـ <FRONTEND_HOSTNAME>
هي localhost:3000
. في هذا العرض التوضيحي، عنوان URL لإعادة التوجيه هو http://localhost:3000/callback
. تأكد من تكوين ذلك في تطبيق casdoor
الخاص بك.
الخطوة 4: تكوين الواجهة الأمامية
تحتاج إلى تثبيت casdoor-js-sdk
وتكوين الـ SDK على النحو التالي:
تثبيت
casdoor-js-sdk
.npm i casdoor-js-sdk
# or
yarn add casdoor-js-sdkإعداد
SDK
.import Sdk from "casdoor-js-sdk";
// Serverurl is the URL where spring security is deployed
export const ServerUrl = "http://BACKEND_HOSTNAME:8080";
const sdkConfig = {
serverUrl: "http://CASDOOR_HOSTNAME:8000",
clientId: "<your client id>",
appName: "<your application name>",
organizationName: "<your organization name>",
redirectPath: "/callback",
};
export const CasdoorSDK = new Sdk(sdkConfig);
الخطوة 5: إعداد عرض توضيحي
أنشئ تطبيق Spring Boot.
أضف بعض التكوينات للتعامل مع JWT.
@EnableWebSecurity
public class SecurityConfig {
private final JwtTokenFilter jwtTokenFilter;
public SecurityConfig(JwtTokenFilter jwtTokenFilter) {
this.jwtTokenFilter = jwtTokenFilter;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// enable CORS and disable CSRF
http = http.cors(corsConfig -> corsConfig
.configurationSource(configurationSource())
).csrf().disable();
// set session management to stateless
http = http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and();
// set permissions on endpoints
http.authorizeHttpRequests(authorize -> authorize
.mvcMatchers("/api/redirect-url", "/api/signin").permitAll()
.mvcMatchers("/api/**").authenticated()
);
// set unauthorized requests exception handler
http = http
.exceptionHandling()
.authenticationEntryPoint(
(request, response, ex) -> ResponseUtils.fail(response, "unauthorized")
)
.and();
// add JWT token filter
http.addFilterBefore(
jwtTokenFilter,
UsernamePasswordAuthenticationFilter.class
);
return http.build();
}
// ...
}
```
أضف فلتر JWT بسيط لاعتراض الطلبات التي تتطلب التحقق من الرمز.
@Component
public class JwtTokenFilter extends OncePerRequestFilter {
private final CasdoorAuthService casdoorAuthService;
public JwtTokenFilter(CasdoorAuthService casdoorAuthService) {
this.casdoorAuthService = casdoorAuthService;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain)
throws ServletException, IOException {
// get authorization header and validate
final String header = request.getHeader(HttpHeaders.AUTHORIZATION);
if (!StringUtils.hasText(header) || !header.startsWith("Bearer ")) {
chain.doFilter(request, response);
return;
}
// get jwt token and validate
final String token = header.split(" ")[1].trim();
// get user identity and set it on the spring security context
UserDetails userDetails = null;
try {
CasdoorUser casdoorUser = casdoorAuthService.parseJwtToken(token);
userDetails = new CustomUserDetails(casdoorUser);
} catch (CasdoorAuthException exception) {
logger.error("casdoor auth exception", exception);
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails,
null,
AuthorityUtils.createAuthorityList("ROLE_casdoor")
);
authentication.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
}عندما يقوم المستخدم بالوصول إلى الواجهة التي تتطلب التحقق من الهوية، سيقوم
JwtTokenFilter
بالحصول على الرمز من رأس الطلبAuthorization
والتحقق منه.حدد
Controller
للتعامل مع تسجيل الدخول للمستخدم إلى Casdoor. بعد تسجيل الدخول للمستخدم، سيتم إعادة توجيهه إلى الخادم وحملcode
وstate
. ثم يحتاج الخادم إلى التحقق من هوية المستخدم من Casdoor والحصول علىtoken
من خلال هذين المعلمتين.@RestController
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
private final CasdoorAuthService casdoorAuthService;
// ...
@PostMapping("/api/signin")
public Result signin(@RequestParam("code") String code, @RequestParam("state") String state) {
try {
String token = casdoorAuthService.getOAuthToken(code, state);
return Result.success(token);
} catch (CasdoorAuthException exception) {
logger.error("casdoor auth exception", exception);
return Result.failure(exception.getMessage());
}
}
// ...
}
```
الخطوة 6: تجربة العرض التوضيحي
يمكنك الوصول إلى التطبيق الأمامي من خلال متصفحك. إذا لم تكن قد سجلت الدخول، سترى زر تسجيل الدخول. انقر عليه، وسيتم إعادة توجيهك إلى صفحة تسجيل الدخول إلى Casdoor.
إذا قمت بزيارة صفحتك الرئيسية،
انقر على زر Casdoor Login
، وسيتم تحويل الصفحة إلى صفحة تسجيل الدخول الخاصة بـ Casdoor.
بعد تسجيل الدخول، سيتم تحويلك إلى /
.