Фильтр 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 перенаправления вы найдете в следующем разделе.
- Получите ваш
Сертификат
на странице редактирования сертификата. - Добавьте провайдера и другие настройки по мере необходимости.
Вы можете получить значения для Имя приложения
, Имя организации
, URL перенаправления
, Client ID
, Client Secret
и Сертификат
на странице настроек приложения. Мы будем использовать их на следующем шаге.
Шаг 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 следующим образом:
Установите
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 {
// включить CORS и отключить CSRF
http = http.cors(corsConfig -> corsConfig
.configurationSource(configurationSource())
).csrf().disable();
// установить управление сессиями как безсостояние
http = http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and();
// установить разрешения на конечные точки
http.authorizeHttpRequests(authorize -> authorize
.mvcMatchers("/api/redirect-url", "/api/signin").permitAll()
.mvcMatchers("/api/**").authenticated()
);
// установить обработчик исключений для неавторизованных запросов
http = http
.exceptionHandling()
.authenticationEntryPoint(
(request, response, ex) -> ResponseUtils.fail(response, "unauthorized")
)
.and();
// добавить фильтр токенов JWT
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.
После входа в систему вы будете перенаправлены на /
.