Перейти до основного вмісту

Фільтр Spring Security з інтеграцією OIDC для Casdoor

Casdoor - це відкритий IDP, який підтримує OIDC та різні інші протоколи. У цій статті ми побачимо, як інтегрувати Casdoor з вашим додатком за допомогою фільтру Spring Security та OIDC.

Крок 1: Розгортання Casdoor

Спочатку вам потрібно розгорнути сервер Casdoor. Дивіться офіційну документацію для інструкцій з встановлення сервера. Після успішного розгортання переконайтеся, що:

  • Сервер Casdoor працює за адресою http://localhost:8000.
  • Ви можете побачити сторінку входу Casdoor за адресою http://localhost:7001.
  • Ви можете перевірити функціональність входу, увійшовши за допомогою облікових даних admin та 123.

Після перевірки цих кроків, слідуйте наступним крокам для інтеграції Casdoor з вашим додатком.

Крок 2: Налаштування додатку Casdoor

  • Створіть новий додаток Casdoor або використовуйте існуючий.
  • Додайте вашу URL-адресу перенаправлення. Більше інформації про отримання URL-адреси перенаправлення ви знайдете в наступному розділі. Налаштування додатку Casdoor
  • Отримайте ваш Certificate на сторінці редагування сертифікатів. Налаштування сертифікації Casdoor
  • Додайте провайдера та інші налаштування за потребою.

Ви можете отримати значення для Application Name, Organization Name, Redirect URL, Client ID, Client Secret та Certificate на сторінці налаштувань додатку. Ми використаємо їх на наступному кроці.

Крок 3: Налаштування Spring Security

Ви можете налаштувати параметри фільтрів Spring Security для обробки токенів:

обережно

Переконайтеся, що ви замінили значення конфігурації на власні, особливо <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 наступним чином:

  1. Встановіть casdoor-js-sdk.

    npm i casdoor-js-sdk 
    # or
    yarn add casdoor-js-sdk
  2. Налаштуйте 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: Налаштування демонстрації

  1. Створіть додаток Spring Boot.

  2. Додайте деякі конфігурації для обробки 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();
    }

    // ...
}
```
  1. Додайте простий 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 та перевіряє його.

  2. Визначте 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. casdoor

Після входу ви будете перенаправлені на /. ресурс