Spring Security Filter ที่มีการรวม OIDC สำหรับ Casdoor
Casdoor เป็น IDP โอเพนซอร์สที่รองรับ OIDC และโปรโตคอลอื่นๆ อีกหลายอย่าง ในบทความนี้ เราจะดูวิธีการรวม Casdoor เข้ากับแอปพลิเคชันของคุณโดยใช้ Spring Security Filter และ 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, ค่าเริ่มต้นของ <FRONTEND_HOSTNAME>
คือ localhost:3000
ในตัวอย่างนี้ URL สำหรับการเปลี่ยนเส้นทางคือ http://localhost:3000/callback
ตรวจสอบให้แน่ใจว่าคุณได้กำหนดค่านี้ในแอปพลิเคชัน casdoor
ของคุณ
ขั้นตอนที่ 4: กำหนดค่า Frontend
คุณต้องติดตั้ง 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: ทดลองใช้ตัวอย่างการทำงาน
คุณสามารถเข้าถึงแอปพลิเคชัน frontend ผ่านเบราว์เซอร์ของคุณ หากคุณยังไม่ได้ล็อกอิน คุณจะเห็นปุ่มล็อกอิน คลิกที่นั้น และคุณจะถูกเปลี่ยนเส้นทางไปยังหน้าล็อกอิน Casdoor
หากคุณเยี่ยมชมหน้า root ของคุณ
คลิกที่ปุ่ม Casdoor Login
และหน้าเว็บจะเปลี่ยนไปยังหน้าล็อกอินของ Casdoor
หลังจากล็อกอินแล้ว คุณจะถูกเปลี่ยนทิศทางไปยัง /