{"id":3439,"date":"2016-08-25T14:43:38","date_gmt":"2016-08-25T12:43:38","guid":{"rendered":"https:\/\/adrhc.go.ro\/wordpress\/?p=3439"},"modified":"2018-03-01T13:30:30","modified_gmt":"2018-03-01T11:30:30","slug":"spring-security","status":"publish","type":"post","link":"https:\/\/adrhc.go.ro\/blog\/spring-security\/","title":{"rendered":"Spring security"},"content":{"rendered":"<p><strong>HTML translated to java config<\/strong><br \/>\nsee also <a href=\"http:\/\/docs.spring.io\/spring-security\/site\/docs\/current\/reference\/html\/jc.html\" target=\"_blank\">Java Configuration<\/a><br \/>\nsee also <a href=\"http:\/\/www.springframework.org\/schema\/security\/spring-security.xsd\" target=\"_blank\">http:\/\/www.springframework.org\/schema\/security\/spring-security.xsd<\/a><\/p>\n<pre class=\"brush:xml;toolbar: false\">\r\n&lt;http security=\"none\" pattern=\"\/resources\/**\"\/>\r\n&lt;http pattern=\"\/api1\/**\" create-session=\"stateless\">\r\n\t&lt;intercept-url pattern=\"\/**\" access=\"authenticated\"\/>\r\n\t&lt;http-basic \/>\r\n&lt;\/http>\r\n&lt;http pattern=\"\/api2\/**\" create-session=\"never\">\r\n\t&lt;intercept-url pattern=\"\/api2\/api21\/**\" access=\"hasRole('ROLE_ADMIN')\"\/>\r\n\t&lt;intercept-url pattern=\"\/api2\/**\" access=\"hasRole('ROLE_USER')\"\/>\r\n\t&lt;http-basic \/>\r\n&lt;\/http>\r\n&lt;http pattern=\"\/api3\/**\">\r\n\t&lt;intercept-url pattern=\"\/api3\/api31\/**\" access=\"hasRole('ROLE_ADMIN')\"\/>\r\n\t&lt;intercept-url pattern=\"\/api3\/api32\/**\" access=\"hasRole('ROLE_USER')\"\/>\r\n\t&lt;intercept-url pattern=\"\/**\" access=\"authenticated\"\/>\r\n\t&lt;http-basic \/>\r\n&lt;\/http>\r\n&lt;http>\r\n\t&lt;intercept-url pattern=\"\/logout\" access=\"permitAll\"\/>\r\n\t&lt;intercept-url pattern=\"\/login\" access=\"permitAll\"\/>\r\n\t&lt;intercept-url pattern=\"\/**\" access=\"hasRole('ROLE_USER')\"&#47;>\r\n\t...\r\n\t&lt;form-login login-page=\"\/services\/session\" login-processing-url=\"\/login\"\r\n\t\t\t\tpassword-parameter=\"password\" username-parameter=\"username\"\r\n\t\t\t\tlogout-success-url=\"\/services\/session\" ... \/>\r\n\t&lt;http-basic \/>\r\n\t&lt;logout invalidate-session=\"true\"\/>\r\n&lt;\/http>\r\n<\/pre>\n<pre class=\"brush:java;toolbar: false\">\r\n@Configuration\r\n@EnableWebSecurity\r\npublic class WebSecurityConfig {\r\n    @Autowired\r\n    private AuthenticationManager am;\r\n\r\n    \/**\r\n     * @param auth\r\n     * @throws Exception\r\n     *\/\r\n    @Autowired\r\n    public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {\r\n        auth.parentAuthenticationManager(this.am);\r\n    }\r\n}\r\n@Configuration\r\n@Order(1)\r\npublic class Api1Authentication extends WebSecurityConfigurerAdapter {\r\n\t@Override\r\n\tprotected void configure(final HttpSecurity httpSecurity) throws Exception {\r\n\t\thttpSecurity.antMatcher(\"\/api1\/**\")\r\n\t\t\t\t\t.authorizeRequests().anyRequest().authenticated()\r\n\t\t\t\t\t.and()\r\n\t\t\t\t\t.httpBasic()\r\n\t\t\t\t\t.and()\r\n\t\t\t\t\t.sessionManagement()\r\n\t\t\t\t\t.sessionCreationPolicy(SessionCreationPolicy.STATELESS);    \r\n\t}\r\n}\r\n@Configuration\r\n@Order(2)\r\npublic class Api2Authentication extends WebSecurityConfigurerAdapter {\r\n\t@Override\r\n\tprotected void configure(final HttpSecurity httpSecurity) throws Exception {\r\n\t\thttpSecurity.antMatcher(\"\/api2\/**\")\r\n\t\t\t\t\t.authorizeRequests()\r\n\t\t\t\t\t.antMatchers(\"\/api2\/api21\/**\").hasRole(\"ADMIN\")\r\n\t\t\t\t\t.antMatchers(\"\/api2\/**\").hasRole(\"USER\")\r\n\t\t\t\t\t.and()\r\n\t\t\t\t\t.httpBasic()\r\n\t\t\t\t\t.and()\r\n\t\t\t\t\t.sessionManagement()\r\n\t\t\t\t\t.sessionCreationPolicy(SessionCreationPolicy.NEVER);    \r\n\t}\r\n}\r\n@Configuration\r\n@Order(3)\r\npublic class Api3Authentication extends WebSecurityConfigurerAdapter {\r\n\t@Override\r\n\tprotected void configure(final HttpSecurity httpSecurity) throws Exception {\r\n\t\thttpSecurity.antMatcher(\"\/api3\/**\")\r\n\t\t\t\t\t.authorizeRequests()\r\n\t\t\t\t\t.antMatchers(\"\/api3\/api31\/**\").hasRole(\"ADMIN\")\r\n\t\t\t\t\t.antMatchers(\"\/api3\/api32\/**\").hasRole(\"USER\")\r\n\t\t\t\t\t.anyRequest().authenticated()\r\n\t\t\t\t\t.and()\r\n\t\t\t\t\t.httpBasic();    \r\n\t}\r\n}\r\n@Configuration\r\npublic class OtherAuthentication extends WebSecurityConfigurerAdapter {\r\n    @Override\r\n    public void configure(final WebSecurity web) throws Exception {\r\n        web.ignoring().antMatchers(\"\/resources\/**\");\r\n    }\r\n\r\n    @Override\r\n    protected void configure(final HttpSecurity httpSecurity) throws Exception {\r\n        httpSecurity.authorizeRequests()\r\n                    .anyRequest().authenticated()\r\n                    .and()\r\n                    .formLogin()\r\n                    .loginPage(\"\/services\/session\")\r\n                    .loginProcessingUrl(\"\/login\")\r\n                    .usernameParameter(\"username\")\r\n                    .passwordParameter(\"password\")\r\n                    .defaultSuccessUrl(\"\/services\/session\")\r\n                    .failureHandler(new DdcAuthenticationFailureHandler())\r\n                    .permitAll()\r\n                    .and()\r\n                    .httpBasic()\r\n                    .and()\r\n                    .logout()\r\n                    .logoutSuccessUrl(\"\/services\/session\")\r\n                    .invalidateHttpSession(true);\r\n    }\r\n}\r\n<\/pre>\n<pre>\r\n<strong>Q1:<\/strong> why should I use antMatcher(\"\/api2\/**\") while anyway the subsequent antMatchers(...) cover the entiy \/api2\/** paths?\r\n<strong>A1:<\/strong> because antMatcher has the purpose of mapping the &lt;http\/> security configuration while antMatchers accompanies authorizeRequests() in order to specify request access conditions (e.g. roles). antMatchers could accompany also requiresChannel() in order to specify the protocol (http, https, any). If not using antMatcher that would be like &lt;http\/> security configuration wouldn't use the pattern attribute (equivalent to using \/**).\r\n\r\nOtherAuthentication allows the use of form and basic authentication (using the order of declaration). So when not authenticated user access \/services\/session (using no Authorization header) he would get back a response (e.g. json containing a CSRF token :D). When the user tries to POST \/services\/session using the received CSRF token he will then be authenticated using basic authentication when he use Authorization header or form authentication otherwise (suppose he uses a valid token otherwise spring will consider a CSRF attack). When one tries to access \/some-not-resources-and-not-api123-path with the header Authorization filled with a valid user\/password than the basic authentication will be enforced and the user will get the result; if user\/password is wrong he will get http code 401. \r\n\r\n\/api2\/** has SessionCreationPolicy.NEVER which means it won't create a session (when using basic authentication) but it might use one when the user already created one like when authenticated with form-authentication.\r\n\r\n\/api1\/** has SessionCreationPolicy.STATELESS which means it will not create a session but also it will invalidate it if found so it does not live well with OtherAuthentication which creates (in order to use) a session. This means that after a form authentication the user will be disconnected after trying to access \/api1\/**.\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>HTML translated to java config see also Java Configuration see also http:\/\/www.springframework.org\/schema\/security\/spring-security.xsd &lt;http security=&#8221;none&#8221; pattern=&#8221;\/resources\/**&#8221;\/> &lt;http pattern=&#8221;\/api1\/**&#8221; create-session=&#8221;stateless&#8221;> &lt;intercept-url pattern=&#8221;\/**&#8221; access=&#8221;authenticated&#8221;\/> &lt;http-basic \/> &lt;\/http> &lt;http pattern=&#8221;\/api2\/**&#8221; create-session=&#8221;never&#8221;> &lt;intercept-url pattern=&#8221;\/api2\/api21\/**&#8221; access=&#8221;hasRole(&#8216;ROLE_ADMIN&#8217;)&#8221;\/> &lt;intercept-url pattern=&#8221;\/api2\/**&#8221; access=&#8221;hasRole(&#8216;ROLE_USER&#8217;)&#8221;\/> &lt;http-basic \/> &lt;\/http> &lt;http pattern=&#8221;\/api3\/**&#8221;> &lt;intercept-url pattern=&#8221;\/api3\/api31\/**&#8221; [&hellip;]<\/p>\n<div class=\"link-more\"><a href=\"https:\/\/adrhc.go.ro\/blog\/spring-security\/#more-3439\" class=\"more-link\">Continue reading &#10142; <span class=\"screen-reader-text\">Spring security<\/span><\/a><\/div>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[36,10,50],"tags":[68],"class_list":["post-3439","post","type-post","status-publish","format-standard","hentry","category-java","category-programming","category-security","tag-spring"],"_links":{"self":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts\/3439","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/comments?post=3439"}],"version-history":[{"count":0,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts\/3439\/revisions"}],"wp:attachment":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/media?parent=3439"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/categories?post=3439"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/tags?post=3439"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}