config.adoc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. = Configuration Migrations
  2. The following steps relate to changes around how to configure `HttpSecurity`, `WebSecurity`, and `AuthenticationManager`.
  3. [[add-configuration-annotation]]
  4. == Add `@Configuration` annotation
  5. In 6.0, `@Configuration` is removed from `@EnableWebSecurity`, `@EnableMethodSecurity`, `@EnableGlobalMethodSecurity`, and `@EnableGlobalAuthentication`.
  6. To prepare for this, wherever you are using one of these annotations, you may need to add `@Configuration`.
  7. For example, `@EnableMethodSecurity` changes from:
  8. [tabs]
  9. ======
  10. Java::
  11. +
  12. [source,java,role="primary"]
  13. ----
  14. @EnableMethodSecurity
  15. public class MyConfiguration {
  16. // ...
  17. }
  18. ----
  19. ======
  20. [tabs]
  21. ======
  22. Kotlin::
  23. +
  24. [source,java,role="primary"]
  25. ----
  26. @EnableMethodSecurity
  27. open class MyConfiguration {
  28. // ...
  29. }
  30. ----
  31. ======
  32. to:
  33. [tabs]
  34. ======
  35. Java::
  36. +
  37. [source,java,role="primary"]
  38. ----
  39. @Configuration
  40. @EnableMethodSecurity
  41. public class MyConfiguration {
  42. // ...
  43. }
  44. ----
  45. ======
  46. [tabs]
  47. ======
  48. Kotlin::
  49. +
  50. [source,java,role="primary"]
  51. ----
  52. @Configuration
  53. @EnableMethodSecurity
  54. open class MyConfiguration {
  55. // ...
  56. }
  57. ----
  58. ======
  59. [[use-new-requestmatchers]]
  60. == Use the new `requestMatchers` methods
  61. In Spring Security 5.8, the {security-api-url}org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.html#antMatchers(java.lang.String...)[`antMatchers`], {security-api-url}org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.html#mvcMatchers(java.lang.String...)[`mvcMatchers`], and {security-api-url}org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.html#regexMatchers(java.lang.String...)[`regexMatchers`] methods were deprecated in favor of new xref:servlet/authorization/authorize-http-requests.adoc#_request_matchers[`requestMatchers` methods].
  62. The new `requestMatchers` methods were added xref:servlet/authorization/authorize-http-requests.adoc[to `authorizeHttpRequests`], `authorizeRequests`, CSRF configuration, `WebSecurityCustomizer` and any other places that had the specialized `RequestMatcher` methods.
  63. The deprecated methods are removed in Spring Security 6.
  64. These new methods have more secure defaults since they choose the most appropriate `RequestMatcher` implementation for your application.
  65. In summary, the new methods choose the `MvcRequestMatcher` implementation if your application has Spring MVC in the classpath, falling back to the `AntPathRequestMatcher` implementation if Spring MVC is not present (aligning the behavior with the Kotlin equivalent methods).
  66. To start using the new methods, you can replace the deprecated methods with the new ones. For example, the following application configuration:
  67. [tabs]
  68. ======
  69. Java::
  70. +
  71. [source,java,role="primary"]
  72. ----
  73. @Configuration
  74. @EnableWebSecurity
  75. public class SecurityConfig {
  76. @Bean
  77. public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  78. http
  79. .authorizeHttpRequests((authz) -> authz
  80. .antMatchers("/api/admin/**").hasRole("ADMIN")
  81. .antMatchers("/api/user/**").hasRole("USER")
  82. .anyRequest().authenticated()
  83. );
  84. return http.build();
  85. }
  86. }
  87. ----
  88. ======
  89. can be changed to:
  90. [tabs]
  91. ======
  92. Java::
  93. +
  94. [source,java,role="primary"]
  95. ----
  96. @Configuration
  97. @EnableWebSecurity
  98. public class SecurityConfig {
  99. @Bean
  100. public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  101. http
  102. .authorizeHttpRequests((authz) -> authz
  103. .requestMatchers("/api/admin/**").hasRole("ADMIN")
  104. .requestMatchers("/api/user/**").hasRole("USER")
  105. .anyRequest().authenticated()
  106. );
  107. return http.build();
  108. }
  109. }
  110. ----
  111. ======
  112. If you have Spring MVC in the classpath and are using the `mvcMatchers` methods, you can replace it with the new methods and Spring Security will choose the `MvcRequestMatcher` implementation for you.
  113. The following configuration:
  114. [tabs]
  115. ======
  116. Java::
  117. +
  118. [source,java,role="primary"]
  119. ----
  120. @Configuration
  121. @EnableWebSecurity
  122. @EnableWebMvc
  123. public class SecurityConfig {
  124. @Bean
  125. SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  126. http
  127. .authorizeHttpRequests((authz) -> authz
  128. .mvcMatchers("/admin/**").hasRole("ADMIN")
  129. .anyRequest().authenticated()
  130. );
  131. return http.build();
  132. }
  133. }
  134. ----
  135. ======
  136. is equivalent to:
  137. [tabs]
  138. ======
  139. Java::
  140. +
  141. [source,java,role="primary"]
  142. ----
  143. @Configuration
  144. @EnableWebSecurity
  145. @EnableWebMvc
  146. public class SecurityConfig {
  147. @Bean
  148. SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  149. http
  150. .authorizeHttpRequests((authz) -> authz
  151. .requestMatchers("/admin/**").hasRole("ADMIN")
  152. .anyRequest().authenticated()
  153. );
  154. return http.build();
  155. }
  156. }
  157. ----
  158. ======
  159. If you are customizing the `servletPath` property of the `MvcRequestMatcher`, you can now use the `MvcRequestMatcher.Builder` to create `MvcRequestMatcher` instances that share the same servlet path:
  160. [tabs]
  161. ======
  162. Java::
  163. +
  164. [source,java,role="primary"]
  165. ----
  166. @Configuration
  167. @EnableWebSecurity
  168. @EnableWebMvc
  169. public class SecurityConfig {
  170. @Bean
  171. SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  172. http
  173. .authorizeHttpRequests((authz) -> authz
  174. .mvcMatchers("/admin").servletPath("/path").hasRole("ADMIN")
  175. .mvcMatchers("/user").servletPath("/path").hasRole("USER")
  176. .anyRequest().authenticated()
  177. );
  178. return http.build();
  179. }
  180. }
  181. ----
  182. ======
  183. The code above can be rewritten using the `MvcRequestMatcher.Builder` and the `requestMatchers` method:
  184. [tabs]
  185. ======
  186. Java::
  187. +
  188. [source,java,role="primary"]
  189. ----
  190. @Configuration
  191. @EnableWebSecurity
  192. @EnableWebMvc
  193. public class SecurityConfig {
  194. @Bean
  195. SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
  196. MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector).servletPath("/path");
  197. http
  198. .authorizeHttpRequests((authz) -> authz
  199. .requestMatchers(mvcMatcherBuilder.pattern("/admin")).hasRole("ADMIN")
  200. .requestMatchers(mvcMatcherBuilder.pattern("/user")).hasRole("USER")
  201. .anyRequest().authenticated()
  202. );
  203. return http.build();
  204. }
  205. }
  206. ----
  207. ======
  208. If you are having problem with the new `requestMatchers` methods, you can always switch back to the `RequestMatcher` implementation that you were using.
  209. For example, if you still want to use `AntPathRequestMatcher` and `RegexRequestMatcher` implementations, you can use the `requestMatchers` method that accepts a `RequestMatcher` instance:
  210. [tabs]
  211. ======
  212. Java::
  213. +
  214. [source,java,role="primary"]
  215. ----
  216. import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
  217. import static org.springframework.security.web.util.matcher.RegexRequestMatcher.regexMatcher;
  218. @Configuration
  219. @EnableWebSecurity
  220. public class SecurityConfig {
  221. @Bean
  222. SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  223. http
  224. .authorizeHttpRequests((authz) -> authz
  225. .requestMatchers(antMatcher("/user/**")).hasRole("USER")
  226. .requestMatchers(antMatcher(HttpMethod.POST, "/user/**")).hasRole("ADMIN")
  227. .requestMatchers(regexMatcher(".*\\?x=y")).hasRole("SPECIAL") // matches /any/path?x=y
  228. .anyRequest().authenticated()
  229. );
  230. return http.build();
  231. }
  232. }
  233. ----
  234. ======
  235. Note that the above sample uses static factory methods from {security-api-url}org/springframework/security/web/util/matcher/AntPathRequestMatcher.html[`AntPathRequestMatcher`] and {security-api-url}org/springframework/security/web/util/matcher/RegexRequestMatcher.html[`RegexRequestMatcher`] to improve readability.
  236. If you are using the `WebSecurityCustomizer` interface, you can replace the deprecated `antMatchers` methods:
  237. [tabs]
  238. ======
  239. Java::
  240. +
  241. [source,java,role="primary"]
  242. ----
  243. @Bean
  244. public WebSecurityCustomizer webSecurityCustomizer() {
  245. return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
  246. }
  247. ----
  248. ======
  249. with their `requestMatchers` counterparts:
  250. [tabs]
  251. ======
  252. Java::
  253. +
  254. [source,java,role="primary"]
  255. ----
  256. @Bean
  257. public WebSecurityCustomizer webSecurityCustomizer() {
  258. return (web) -> web.ignoring().requestMatchers("/ignore1", "/ignore2");
  259. }
  260. ----
  261. ======
  262. The same way, if you are customizing the CSRF configuration to ignore some paths, you can replace the deprecated methods with the `requestMatchers` methods:
  263. [tabs]
  264. ======
  265. Java::
  266. +
  267. [source,java,role="primary"]
  268. ----
  269. @Bean
  270. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  271. http
  272. .csrf((csrf) -> csrf
  273. .ignoringAntMatchers("/no-csrf")
  274. );
  275. return http.build();
  276. }
  277. ----
  278. ======
  279. can be changed to:
  280. [tabs]
  281. ======
  282. Java::
  283. +
  284. [source,java,role="primary"]
  285. ----
  286. @Bean
  287. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  288. http
  289. .csrf((csrf) -> csrf
  290. .ignoringRequestMatchers("/no-csrf")
  291. );
  292. return http.build();
  293. }
  294. ----
  295. ======
  296. [[use-new-security-matchers]]
  297. == Use the new `securityMatchers` methods
  298. In Spring Security 5.8, the `antMatchers`, `mvcMatchers` and `requestMatchers` methods from `HttpSecurity` were deprecated in favor of new `securityMatchers` methods.
  299. Note that these methods are not the same from `authorizeHttpRequests` methods <<use-new-requestmatchers,which were deprecated>> in favor of the `requestMatchers` methods.
  300. However, the `securityMatchers` methods are similar to the `requestMatchers` methods in the sense that they will choose the most appropriate `RequestMatcher` implementation for your application.
  301. In summary, the new methods choose the `MvcRequestMatcher` implementation if your application has Spring MVC in the classpath, falling back to the `AntPathRequestMatcher` implementation if Spring MVC is not present (aligning the behavior with the Kotlin equivalent methods).
  302. Another reason for adding the `securityMatchers` methods is to avoid confusion with the `requestMatchers` methods from `authorizeHttpRequests`.
  303. The following configuration:
  304. [tabs]
  305. ======
  306. Java::
  307. +
  308. [source,java,role="primary"]
  309. ----
  310. @Bean
  311. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  312. http
  313. .antMatcher("/api/**", "/app/**")
  314. .authorizeHttpRequests((authz) -> authz
  315. .requestMatchers("/api/admin/**").hasRole("ADMIN")
  316. .anyRequest().authenticated()
  317. );
  318. return http.build();
  319. }
  320. ----
  321. ======
  322. can be rewritten using the `securityMatchers` methods:
  323. [tabs]
  324. ======
  325. Java::
  326. +
  327. [source,java,role="primary"]
  328. ----
  329. @Bean
  330. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  331. http
  332. .securityMatcher("/api/**", "/app/**")
  333. .authorizeHttpRequests((authz) -> authz
  334. .requestMatchers("/api/admin/**").hasRole("ADMIN")
  335. .anyRequest().authenticated()
  336. );
  337. return http.build();
  338. }
  339. ----
  340. ======
  341. If you are using a custom `RequestMatcher` in your `HttpSecurity` configuration:
  342. [tabs]
  343. ======
  344. Java::
  345. +
  346. [source,java,role="primary"]
  347. ----
  348. @Bean
  349. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  350. http
  351. .requestMatcher(new MyCustomRequestMatcher())
  352. .authorizeHttpRequests((authz) -> authz
  353. .requestMatchers("/api/admin/**").hasRole("ADMIN")
  354. .anyRequest().authenticated()
  355. );
  356. return http.build();
  357. }
  358. public class MyCustomRequestMatcher implements RequestMatcher {
  359. // ...
  360. }
  361. ----
  362. ======
  363. you can do the same using `securityMatcher`:
  364. [tabs]
  365. ======
  366. Java::
  367. +
  368. [source,java,role="primary"]
  369. ----
  370. @Bean
  371. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  372. http
  373. .securityMatcher(new MyCustomRequestMatcher())
  374. .authorizeHttpRequests((authz) -> authz
  375. .requestMatchers("/api/admin/**").hasRole("ADMIN")
  376. .anyRequest().authenticated()
  377. );
  378. return http.build();
  379. }
  380. public class MyCustomRequestMatcher implements RequestMatcher {
  381. // ...
  382. }
  383. ----
  384. ======
  385. If you are combining multiple `RequestMatcher` implementations in your `HttpSecurity` configuration:
  386. [tabs]
  387. ======
  388. Java::
  389. +
  390. [source,java,role="primary"]
  391. ----
  392. @Bean
  393. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  394. http
  395. .requestMatchers((matchers) -> matchers
  396. .antMatchers("/api/**", "/app/**")
  397. .mvcMatchers("/admin/**")
  398. .requestMatchers(new MyCustomRequestMatcher())
  399. )
  400. .authorizeHttpRequests((authz) -> authz
  401. .requestMatchers("/admin/**").hasRole("ADMIN")
  402. .anyRequest().authenticated()
  403. );
  404. return http.build();
  405. }
  406. ----
  407. ======
  408. you can change it by using `securityMatchers`:
  409. [tabs]
  410. ======
  411. Java::
  412. +
  413. [source,java,role="primary"]
  414. ----
  415. @Bean
  416. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  417. http
  418. .securityMatchers((matchers) -> matchers
  419. .requestMatchers("/api/**", "/app/**", "/admin/**")
  420. .requestMatchers(new MyCustomRequestMatcher())
  421. )
  422. .authorizeHttpRequests((authz) -> authz
  423. .requestMatchers("/admin/**").hasRole("ADMIN")
  424. .anyRequest().authenticated()
  425. );
  426. return http.build();
  427. }
  428. ----
  429. ======
  430. If you are having problems with the `securityMatchers` methods choosing the `RequestMatcher` implementation for you, you can always choose the `RequestMatcher` implementation yourself:
  431. [tabs]
  432. ======
  433. Java::
  434. +
  435. [source,java,role="primary"]
  436. ----
  437. import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
  438. @Bean
  439. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  440. http
  441. .securityMatchers((matchers) -> matchers
  442. .requestMatchers(antMatcher("/api/**"), antMatcher("/app/**"))
  443. )
  444. .authorizeHttpRequests((authz) -> authz
  445. .requestMatchers(antMatcher("/api/admin/**")).hasRole("ADMIN")
  446. .anyRequest().authenticated()
  447. );
  448. return http.build();
  449. }
  450. ----
  451. ======
  452. == Stop Using `WebSecurityConfigurerAdapter`
  453. === Publish a `SecurityFilterChain` Bean
  454. Spring Security 5.4 introduced the capability to publish a `SecurityFilterChain` bean instead of extending `WebSecurityConfigurerAdapter`.
  455. In 6.0, `WebSecurityConfigurerAdapter` is removed.
  456. To prepare for this change, you can replace constructs like:
  457. [tabs]
  458. ======
  459. Java::
  460. +
  461. [source,java,role="primary"]
  462. ----
  463. @Configuration
  464. public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  465. @Override
  466. protected void configure(HttpSecurity http) throws Exception {
  467. http
  468. .authorizeHttpRequests((authorize) -> authorize
  469. .anyRequest().authenticated()
  470. )
  471. .httpBasic(withDefaults());
  472. }
  473. }
  474. ----
  475. Kotlin::
  476. +
  477. [source,kotlin,role="secondary"]
  478. ----
  479. @Configuration
  480. open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
  481. @Override
  482. override fun configure(val http: HttpSecurity) {
  483. http {
  484. authorizeHttpRequests {
  485. authorize(anyRequest, authenticated)
  486. }
  487. httpBasic {}
  488. }
  489. }
  490. }
  491. ----
  492. ======
  493. with:
  494. [tabs]
  495. ======
  496. Java::
  497. +
  498. [source,java,role="primary"]
  499. ----
  500. @Configuration
  501. public class SecurityConfiguration {
  502. @Bean
  503. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  504. http
  505. .authorizeHttpRequests((authorize) -> authorize
  506. .anyRequest().authenticated()
  507. )
  508. .httpBasic(withDefaults());
  509. return http.build();
  510. }
  511. }
  512. ----
  513. Kotlin::
  514. +
  515. [source,kotlin,role="secondary"]
  516. ----
  517. @Configuration
  518. open class SecurityConfiguration {
  519. @Bean
  520. fun filterChain(http: HttpSecurity): SecurityFilterChain {
  521. http {
  522. authorizeHttpRequests {
  523. authorize(anyRequest, authenticated)
  524. }
  525. httpBasic {}
  526. }
  527. return http.build()
  528. }
  529. }
  530. ----
  531. ======
  532. === Publish a `WebSecurityCustomizer` Bean
  533. Spring Security 5.4 https://github.com/spring-projects/spring-security/issues/8978[introduced `WebSecurityCustomizer`] to replace `configure(WebSecurity web)` in `WebSecurityConfigurerAdapter`.
  534. To prepare for its removal, you can replace code like the following:
  535. [tabs]
  536. ======
  537. Java::
  538. +
  539. [source,java,role="primary"]
  540. ----
  541. @Configuration
  542. public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  543. @Override
  544. public void configure(WebSecurity web) {
  545. web.ignoring().antMatchers("/ignore1", "/ignore2");
  546. }
  547. }
  548. ----
  549. Kotlin::
  550. +
  551. [source,kotlin,role="secondary"]
  552. ----
  553. @Configuration
  554. open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
  555. override fun configure(val web: WebSecurity) {
  556. web.ignoring().antMatchers("/ignore1", "/ignore2")
  557. }
  558. }
  559. ----
  560. ======
  561. with:
  562. [tabs]
  563. ======
  564. Java::
  565. +
  566. [source,java,role="primary"]
  567. ----
  568. @Configuration
  569. public class SecurityConfiguration {
  570. @Bean
  571. public WebSecurityCustomizer webSecurityCustomizer() {
  572. return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
  573. }
  574. }
  575. ----
  576. Kotlin::
  577. +
  578. [source,kotlin,role="secondary"]
  579. ----
  580. @Configuration
  581. open class SecurityConfiguration {
  582. @Bean
  583. fun webSecurityCustomizer(): WebSecurityCustomizer {
  584. return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2")
  585. }
  586. }
  587. ----
  588. ======
  589. === Publish an `AuthenticationManager` Bean
  590. As part of `WebSecurityConfigurerAdapter` removal, `configure(AuthenticationManagerBuilder)` is also removed.
  591. Preparing for its removal will differ based on your reason for using it.
  592. ==== LDAP Authentication
  593. If you are using `auth.ldapAuthentication()` for xref:servlet/authentication/passwords/ldap.adoc[LDAP authentication support], you can replace:
  594. [tabs]
  595. ======
  596. Java::
  597. +
  598. [source,java,role="primary"]
  599. ----
  600. @Configuration
  601. public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  602. @Override
  603. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  604. auth
  605. .ldapAuthentication()
  606. .userDetailsContextMapper(new PersonContextMapper())
  607. .userDnPatterns("uid={0},ou=people")
  608. .contextSource()
  609. .port(0);
  610. }
  611. }
  612. ----
  613. Kotlin::
  614. +
  615. [source,kotlin,role="secondary"]
  616. ----
  617. @Configuration
  618. open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
  619. override fun configure(auth: AuthenticationManagerBuilder) {
  620. auth
  621. .ldapAuthentication()
  622. .userDetailsContextMapper(PersonContextMapper())
  623. .userDnPatterns("uid={0},ou=people")
  624. .contextSource()
  625. .port(0)
  626. }
  627. }
  628. ----
  629. ======
  630. with:
  631. [tabs]
  632. ======
  633. Java::
  634. +
  635. [source,java,role="primary"]
  636. ----
  637. @Configuration
  638. public class SecurityConfiguration {
  639. @Bean
  640. public EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean() {
  641. EmbeddedLdapServerContextSourceFactoryBean contextSourceFactoryBean =
  642. EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer();
  643. contextSourceFactoryBean.setPort(0);
  644. return contextSourceFactoryBean;
  645. }
  646. @Bean
  647. AuthenticationManager ldapAuthenticationManager(BaseLdapPathContextSource contextSource) {
  648. LdapBindAuthenticationManagerFactory factory =
  649. new LdapBindAuthenticationManagerFactory(contextSource);
  650. factory.setUserDnPatterns("uid={0},ou=people");
  651. factory.setUserDetailsContextMapper(new PersonContextMapper());
  652. return factory.createAuthenticationManager();
  653. }
  654. }
  655. ----
  656. Kotlin::
  657. +
  658. [source,kotlin,role="secondary"]
  659. ----
  660. @Configuration
  661. open class SecurityConfiguration {
  662. @Bean
  663. fun contextSourceFactoryBean(): EmbeddedLdapServerContextSourceFactoryBean {
  664. val contextSourceFactoryBean: EmbeddedLdapServerContextSourceFactoryBean =
  665. EmbeddedLdapServerContextSourceFactoryBean.fromEmbeddedLdapServer()
  666. contextSourceFactoryBean.setPort(0)
  667. return contextSourceFactoryBean
  668. }
  669. @Bean
  670. fun ldapAuthenticationManager(val contextSource: BaseLdapPathContextSource): AuthenticationManager {
  671. val factory = LdapBindAuthenticationManagerFactory(contextSource)
  672. factory.setUserDnPatterns("uid={0},ou=people")
  673. factory.setUserDetailsContextMapper(PersonContextMapper())
  674. return factory.createAuthenticationManager()
  675. }
  676. }
  677. ----
  678. ======
  679. ==== JDBC Authentication
  680. If you are using `auth.jdbcAuthentication()` for xref:servlet/authentication/passwords/jdbc.adoc[JDBC Authentication support], you can replace:
  681. [tabs]
  682. ======
  683. Java::
  684. +
  685. [source,java,role="primary"]
  686. ----
  687. @Configuration
  688. public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  689. @Bean
  690. public DataSource dataSource() {
  691. return new EmbeddedDatabaseBuilder()
  692. .setType(EmbeddedDatabaseType.H2)
  693. .build();
  694. }
  695. @Override
  696. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  697. UserDetails user = User.withDefaultPasswordEncoder()
  698. .username("user")
  699. .password("password")
  700. .roles("USER")
  701. .build();
  702. auth.jdbcAuthentication()
  703. .withDefaultSchema()
  704. .dataSource(this.dataSource)
  705. .withUser(user);
  706. }
  707. }
  708. ----
  709. Kotlin::
  710. +
  711. [source,kotlin,role="secondary"]
  712. ----
  713. @Configuration
  714. open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
  715. @Bean
  716. fun dataSource(): DataSource {
  717. return EmbeddedDatabaseBuilder()
  718. .setType(EmbeddedDatabaseType.H2)
  719. .build()
  720. }
  721. override fun configure(val auth: AuthenticationManagerBuilder) {
  722. UserDetails user = User.withDefaultPasswordEncoder()
  723. .username("user")
  724. .password("password")
  725. .roles("USER")
  726. .build()
  727. auth.jdbcAuthentication()
  728. .withDefaultSchema()
  729. .dataSource(this.dataSource)
  730. .withUser(user)
  731. }
  732. }
  733. ----
  734. ======
  735. with:
  736. [tabs]
  737. ======
  738. Java::
  739. +
  740. [source,java,role="primary"]
  741. ----
  742. @Configuration
  743. public class SecurityConfiguration {
  744. @Bean
  745. public DataSource dataSource() {
  746. return new EmbeddedDatabaseBuilder()
  747. .setType(EmbeddedDatabaseType.H2)
  748. .addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION)
  749. .build();
  750. }
  751. @Bean
  752. public UserDetailsManager users(DataSource dataSource) {
  753. UserDetails user = User.withDefaultPasswordEncoder()
  754. .username("user")
  755. .password("password")
  756. .roles("USER")
  757. .build();
  758. JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
  759. users.createUser(user);
  760. return users;
  761. }
  762. }
  763. ----
  764. Kotlin::
  765. +
  766. [source,kotlin,role="secondary"]
  767. ----
  768. @Configuration
  769. open class SecurityConfiguration {
  770. @Bean
  771. fun dataSource(): DataSource {
  772. return EmbeddedDatabaseBuilder()
  773. .setType(EmbeddedDatabaseType.H2)
  774. .addScript(JdbcDaoImpl.DEFAULT_USER_SCHEMA_DDL_LOCATION)
  775. .build()
  776. }
  777. @Bean
  778. fun users(val dataSource: DataSource): UserDetailsManager {
  779. val user = User.withDefaultPasswordEncoder()
  780. .username("user")
  781. .password("password")
  782. .roles("USER")
  783. .build()
  784. val users = JdbcUserDetailsManager(dataSource)
  785. users.createUser(user)
  786. return users
  787. }
  788. }
  789. ----
  790. ======
  791. ==== In-Memory Authentication
  792. If you are using `auth.inMemoryAuthentication()` for xref:servlet/authentication/passwords/in-memory.adoc[In-Memory Authentication support], you can replace:
  793. [tabs]
  794. ======
  795. Java::
  796. +
  797. [source,java,role="primary"]
  798. ----
  799. @Configuration
  800. public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  801. @Override
  802. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  803. UserDetails user = User.withDefaultPasswordEncoder()
  804. .username("user")
  805. .password("password")
  806. .roles("USER")
  807. .build();
  808. auth.inMemoryAuthentication()
  809. .withUser(user);
  810. }
  811. }
  812. ----
  813. Kotlin::
  814. +
  815. [source,kotlin,role="secondary"]
  816. ----
  817. @Configuration
  818. open class SecurityConfiguration: WebSecurityConfigurerAdapter() {
  819. override fun configure(val auth: AuthenticationManagerBuilder) {
  820. val user = User.withDefaultPasswordEncoder()
  821. .username("user")
  822. .password("password")
  823. .roles("USER")
  824. .build()
  825. auth.inMemoryAuthentication()
  826. .withUser(user)
  827. }
  828. }
  829. ----
  830. ======
  831. with:
  832. [tabs]
  833. ======
  834. Java::
  835. +
  836. [source,java,role="primary"]
  837. ----
  838. @Configuration
  839. public class SecurityConfiguration {
  840. @Bean
  841. public InMemoryUserDetailsManager userDetailsService() {
  842. UserDetails user = User.withDefaultPasswordEncoder()
  843. .username("user")
  844. .password("password")
  845. .roles("USER")
  846. .build();
  847. return new InMemoryUserDetailsManager(user);
  848. }
  849. }
  850. ----
  851. Kotlin::
  852. +
  853. [source,kotlin,role="secondary"]
  854. ----
  855. @Configuration
  856. open class SecurityConfiguration {
  857. @Bean
  858. fun userDetailsService(): InMemoryUserDetailsManager {
  859. UserDetails user = User.withDefaultPasswordEncoder()
  860. .username("user")
  861. .password("password")
  862. .roles("USER")
  863. .build()
  864. return InMemoryUserDetailsManager(user)
  865. }
  866. }
  867. ----
  868. ======
  869. == Add `@Configuration` to `@Enable*` annotations
  870. In 6.0, all Spring Security's `@Enable*` annotations had their `@Configuration` removed.
  871. While convenient, it was not consistent with the rest of the Spring projects and most notably Spring Framework's `@Enable*` annotations.
  872. Additionally, the introduction of support for `@Configuration(proxyBeanMethods=false)` in Spring Framework provides another reason to remove `@Configuration` meta-annotation from Spring Security's `@Enable*` annotations and allow users to opt into their preferred configuration mode.
  873. The following annotations had their `@Configuration` removed:
  874. - `@EnableGlobalAuthentication`
  875. - `@EnableGlobalMethodSecurity`
  876. - `@EnableMethodSecurity`
  877. - `@EnableReactiveMethodSecurity`
  878. - `@EnableWebSecurity`
  879. - `@EnableWebFluxSecurity`
  880. For example, if you are using `@EnableWebSecurity`, you will need to change:
  881. [tabs]
  882. ======
  883. Java::
  884. +
  885. [source,java,role="primary"]
  886. ----
  887. @EnableWebSecurity
  888. public class SecurityConfig {
  889. // ...
  890. }
  891. ----
  892. ======
  893. to:
  894. [tabs]
  895. ======
  896. Java::
  897. +
  898. [source,java,role="primary"]
  899. ----
  900. @Configuration
  901. @EnableWebSecurity
  902. public class SecurityConfig {
  903. // ...
  904. }
  905. ----
  906. ======
  907. And the same applies to every other annotation listed above.
  908. === Other Scenarios
  909. If you are using `AuthenticationManagerBuilder` for something more sophisticated, you can xref:servlet/authentication/architecture.adoc#servlet-authentication-authenticationmanager[publish your own `AuthenticationManager` `@Bean`] or wire an `AuthenticationManager` instance into the `HttpSecurity` DSL with {security-api-url}org/springframework/security/config/annotation/web/builders/HttpSecurity.html#authenticationManager(org.springframework.security.authentication.AuthenticationManager)[`HttpSecurity#authenticationManager`].