Spring security added (disabled)
authorelgekko <vasary@elgekko.net>
Mon, 22 May 2023 20:27:40 +0000 (22:27 +0200)
committerelgekko <vasary@elgekko.net>
Mon, 22 May 2023 20:27:40 +0000 (22:27 +0200)
KB.md
lis-app/src/main/java/hu/user/lis/app/Main.java
lis-ui/pom.xml
lis-ui/src/main/java/hu/user/lis/ui/config/WebSecurityConfig.java [new file with mode: 0644]
lis-ui/src/main/resources/web/login.zul [new file with mode: 0644]

diff --git a/KB.md b/KB.md
index 7bd7e77fde50153a89eeae924fcfdc791cf74e21..62aa230f1cbd1754987705eb9b415ccbd938c378 100644 (file)
--- a/KB.md
+++ b/KB.md
@@ -53,6 +53,12 @@ https://www.zkoss.org/javadoc/8.5.0/jsdoc/index.html?zk/Widget.html
 http://books.zkoss.org/zk-mvvm-book/8.0/index.html
 https://www.zkoss.org/documentation#References
 
+##### Spring ZK Security
+
+https://www.zkoss.org/wiki/ZK_Spring_Essentials/Working_with_ZK_Spring/Working_with_ZK_Spring_Security/Secure_a_ZK_Application_with_Spring_Security
+https://www.zkoss.org/wiki/ZK_Spring_Essentials/Working_with_ZK_Spring/Working_with_ZK_Spring_Security/Add_Security_in_the_View_Layer
+(To enable remove @SpringBootApplication with exludes and @ComponentScan)
+
 ##### ZK Style
 
 https://www.zkoss.org/wiki/ZK_Developer's_Reference/Theming_and_Styling/ZK_Official_Themes
index f4eb02988e44ef3addadf98d8516284344fed472..d170059ed361ebabcad4a858f097b3e5d1bf4f36 100644 (file)
@@ -5,6 +5,7 @@
 
 package hu.user.lis.app;
 
+import hu.user.lis.ui.config.WebSecurityConfig;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.springframework.boot.SpringApplication;
@@ -13,11 +14,19 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
 import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.FilterType;
 import org.springframework.context.event.ContextRefreshedEvent;
 import org.springframework.core.SpringVersion;
 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 
-@SpringBootApplication(scanBasePackages = {"hu.user.lis"})
+//@SpringBootApplication(scanBasePackages = {"hu.user.lis"})
+@SpringBootApplication(exclude = {
+        org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class,
+        org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration.class}
+)
+@ComponentScan(basePackages = {"hu.user.lis"}, excludeFilters = {
+        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = WebSecurityConfig.class)})
 @EnableWebMvc
 public class Main extends SpringBootServletInitializer implements ApplicationListener<ContextRefreshedEvent> {
 
@@ -32,19 +41,18 @@ public class Main extends SpringBootServletInitializer implements ApplicationLis
 //        AnsiConsole.systemUninstall();
     }
 
-    @Override
-    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
-        logger.info("Starting configure");
-        return builder.sources(Main.class);
-    }
-
-
     private static void dumpComponents(ApplicationContext applicationContext) {
         for (String beanName : applicationContext.getBeanDefinitionNames()) {
             logger.info("Found {}", beanName);
         }
     }
 
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
+        logger.info("Starting configure");
+        return builder.sources(Main.class);
+    }
+
     @Override
     public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
         logger.info("Context refreshed");
index 6a6d746d9d39157bfb65ee0cca297504c2df43b4..904dc3fb3fce2943dd26bc1e91d9aa58938616f0 100644 (file)
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.javassist</groupId>
             <artifactId>javassist</artifactId>
diff --git a/lis-ui/src/main/java/hu/user/lis/ui/config/WebSecurityConfig.java b/lis-ui/src/main/java/hu/user/lis/ui/config/WebSecurityConfig.java
new file mode 100644 (file)
index 0000000..45d38a4
--- /dev/null
@@ -0,0 +1,64 @@
+package hu.user.lis.ui.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager;
+
+/**
+ * This is an example of minimal configuration for ZK + Spring Security, we open as less access as possible to run a ZK-based application.
+ * Please understand the configuration and modify it upon your requirement.
+ */
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+    private static final String ZUL_FILES = "/zkau/web/**/*.zul";
+    private static final String ZK_RESOURCES = "/zkres/**";
+    // allow desktop cleanup after logout or when reloading login page
+    private static final String REMOVE_DESKTOP_REGEX = "/zkau\\?dtid=.*&cmd_0=rmDesktop&.*";
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        // you need to disable spring CSRF to make ZK AU pass security filter
+        // ZK already sends a AJAX request with a built-in CSRF token,
+        // please refer to https://www.zkoss.org/wiki/ZK%20Developer's%20Reference/Security%20Tips/Cross-site%20Request%20Forgery
+        http.csrf().disable();
+        http.authorizeRequests()
+                .antMatchers(ZUL_FILES).denyAll() // block direct access to zul under class path web resource folder
+                .antMatchers(HttpMethod.GET, ZK_RESOURCES).permitAll() // allow zk resources
+                .regexMatchers(HttpMethod.GET, REMOVE_DESKTOP_REGEX).permitAll() // allow desktop cleanup
+                .requestMatchers(req -> "rmDesktop".equals(req.getParameter("cmd_0"))).permitAll() // allow desktop cleanup from ZATS
+                .mvcMatchers("/", "/login", "/logout").permitAll() //permit the URL for login and logout
+                .mvcMatchers("/secure").hasRole("USER")
+                .anyRequest().authenticated() //enforce all requests to be authenticated
+                .and()
+                .formLogin()
+                .loginPage("/login").defaultSuccessUrl("/secure/main")
+                .and()
+                .logout().logoutUrl("/logout").logoutSuccessUrl("/");
+    }
+
+    /**
+     * Creates an {@link InMemoryUserDetailsManager} for demo/testing purposes only. DON'T use this in production, see: {@link User#withUserDetails}!
+     *
+     * @return userDetailsService
+     */
+    @Bean
+    @Override
+    public UserDetailsService userDetailsService() {
+        UserDetails user =
+                User.withDefaultPasswordEncoder()
+                        .username("user")
+                        .password("password")
+                        .roles("USER")
+                        .build();
+
+        return new InMemoryUserDetailsManager(user);
+    }
+}
\ No newline at end of file
diff --git a/lis-ui/src/main/resources/web/login.zul b/lis-ui/src/main/resources/web/login.zul
new file mode 100644 (file)
index 0000000..0134778
--- /dev/null
@@ -0,0 +1,26 @@
+<zk xmlns:n="native">
+    <n:form action="/login" method="POST">
+        <grid width="450px">
+            <columns>
+                <column width="160px" />
+                <column width="280px" />
+            </columns>
+            <rows>
+                <row spans="2" align="center">
+                    <label value="LOGIN"/>
+                </row>
+                <row>
+                    <label value="User :"/>
+                    <textbox name="username" value="user"/></row>
+                <row>
+                    <label value="Password :"/>
+                    <textbox type="password" name="password" value="password"/> </row>
+                <row spans="2" align="right">
+                    <hlayout>
+                    <button type="reset" label="Reset" /> <button type="submit" label="Login" />
+                    </hlayout>
+                </row>
+            </rows>
+        </grid>
+    </n:form>
+</zk>
\ No newline at end of file