• SpringSecurity(二): 自定义登录页面


    表单认证方式 Spring Security 默认提供了一个 bootstrap 登录页面,如果希望使用自定义的登录页面怎么办?
    .1.CustomLoginController用于实现认证(登录)处理。
    /**
     * 登录处理
     */
    @Controller
    public class CustomLoginController {
    
        /**
         * 前往认证(登录)页面
         * @return
         */
        @RequestMapping("/login/page")
        public String toLogin(){
            return "login"; 
        }
    }

    2.指定跳转自定义登录页面的URL
    SpringSecurityConfig.confifigure(HttpSecurity http) 中使用 loginPage("/login/page") 指定前往自定义的登录页面认证请求
      2.1. 登录表单默认的 action="/login"  , 通过 loginProcessingUrl("/login/form") 修改为 /login/form 。
      2.2. 登录表单的用户名参数名默认是 name="username" , 通过 usernameParameter("name") 修改为 name 。
      2.3. 登录表单的密码参考名默认是 name="password" ,通过 passwordParameter("pwd") 修改为 pwd 。
    /**
         * 资源权限配置(过滤器链):
         * 1、被拦截的资源
         * 2、资源所对应的角色权限
         * 3、定义认证方式:httpBasic 、httpForm
         * 4、定制登录页面、登录请求地址、错误处理方式
         * 5、自定义 spring security 过滤器
         *
         * @param http
         * @throws Exception
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //http.httpBasic()//采用httpBasic 认证方式
            http.formLogin()
                    .loginPage("/login/page")// 交给 /login/page 响应认证(登录)页面
                    .loginProcessingUrl("/login/form")  // 登录表单提交处理Url, 默认是 /login
                    .usernameParameter("name") // 默认用户名的属性名是 username
                    .passwordParameter("pwd") // 默认密码的属性名是 password
                    .and()
                    .authorizeRequests()//认证请求
                    .antMatchers("/login/page").permitAll()//自定义登录页不需要认证,放行
                    .anyRequest().authenticated();// 所有进入应用的HTTP请求都要进行认证
        }
    
        /**
         * 放行静态资源(js css 等)
         *
         * @param web
         */
        @Override
        public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/dist/**", "/modules/**", "/plugins/**");
      }

    未认证之前访问(端口号设置为了80)localhost/index 或localhost/或localhost 都能进入到首页。

    @Controller
    public class MainController {
        // 首页
        @RequestMapping({"/index", "/", ""})
        public String index() {
            return "index";
        }
    
    }

    开启认证(未自定义登录页面),进行首页访问将重定向到http://localhost/login (Spring Security默认的表单认证url为"/login") 使用Spring Security 默认提供了一个 bootstrap 登录页面去认证,

     现自定义登录页面为security-web项目中resource下的login.html,并在configure(HttpSecurity http)中配置 http.formLogin().loginPage("/login/page")  ,进行首页访问将重定向到http://localhost/login/page  使用自定义登录页面去认证

    3.在当前配置中的认证相关URL是写死,这些 URL 根据应用系统的不同,可能需要配置不同的URL,那我们可以抽取到 application.yml 进行可配置。

    web:
      security:
        authentication:
          loginPage: /login/page # 响应认证(登录)页面URL
          loginProcessingUrl: /login/form # 自定义登录表单提交处理Url
          usernameParameter: name # 登录表单用户名的属性名
          passwordParameter: pwd # 登录表单密码的属性名
          staticPaths: # 静态资源 "/dist/**", "/modules/**", "/plugins/**"
            - /dist/**
            - /modules/**
            - /plugins/**

    自定义认证相关动态配置类SecurityProperties读取application.yml 中的配置信息

    /**
     * 认证相关动态配置
     */
    @Component
    @ConfigurationProperties(prefix = "web.security.authentication")
    @Data
    public class SecurityProperties {
    
        // application.yml 没配置取默认值
        private String loginPage = "/login/page";
        private String loginProcessingUrl = "/login/form";
        private String usernameParameter = "name";
        private String passwordParameter = "pwd";
        private String[] staticPaths = {"/dist/**", "/modules/**", "/plugins/**"};
    }

    在SpringSecurityConfig中注入SecurityProperties 

       @Autowired
        SecurityProperties securityProperties;
    
        /**
         * 资源权限配置(过滤器链):
         * 1、被拦截的资源
         * 2、资源所对应的角色权限
         * 3、定义认证方式:httpBasic 、httpForm
         * 4、定制登录页面、登录请求地址、错误处理方式
         * 5、自定义 spring security 过滤器
         *
         * @param http
         * @throws Exception
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.formLogin()
                    .loginPage(securityProperties.getLoginPage())// 交给 /login/page 响应认证(登录)页面
                    .loginProcessingUrl(securityProperties.getLoginProcessingUrl())  // 登录表单提交处理Url, 默认是 /login
                    .usernameParameter(securityProperties.getUsernameParameter()) // 默认用户名的属性名是 username
                    .passwordParameter(securityProperties.getPasswordParameter()) // 默认密码的属性名是 password
                    .and()
                    .authorizeRequests()//认证请求
                    .antMatchers(securityProperties.getLoginPage()).permitAll()//自定义登录页不需要认证
                    .anyRequest().authenticated();// 所有进入应用的HTTP请求都要进行认证
        }
    
        /**
         * 放行静态资源(js css 等)
         *
         * @param web
         */
        @Override
        public void configure(WebSecurity web) {
            web.ignoring().antMatchers(securityProperties.getStaticPaths());
        }

    4.完整代码

    /**
     * 安全配置类作为安全控制中心, 用于实现身份认证与授权配置功能
     */
    @Configuration
    @EnableWebSecurity //启动 SpringSecurity 过滤器链功能
    public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        SecurityProperties securityProperties;
    
        Logger logger = LoggerFactory.getLogger(SpringSecurityConfig.class);
    
    
        @Bean
        public BCryptPasswordEncoder bCryptPasswordEncoder() {
            // 加密存储   明文+随机盐值
            return new BCryptPasswordEncoder();
        }
    
    
        /**
         * 认证管理器:
         * 1、认证信息提供方式(用户名、密码、当前用户的资源权限)
         * 2、可采用内存存储方式,也可能采用数据库方式等
         *
         * @param auth
         * @throws Exception
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            //基于内存存储认证信息 存储的密码必须是加密后的 不然会报错:There is no PasswordEncoder mapped for the id "null"
            //auth.inMemoryAuthentication().withUser("zcc").password("123").authorities("ADMIN");
            String password = bCryptPasswordEncoder().encode("123");
            logger.info("加密后的密码:" + password);
            auth.inMemoryAuthentication().withUser("zcc").password(password).authorities("ADMIN");
        }
    
        /**
         * 资源权限配置(过滤器链):
         * 1、被拦截的资源
         * 2、资源所对应的角色权限
         * 3、定义认证方式:httpBasic 、httpForm
         * 4、定制登录页面、登录请求地址、错误处理方式
         * 5、自定义 spring security 过滤器
         *
         * @param http
         * @throws Exception
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //http.httpBasic()//采用httpBasic 认证方式
            /*http.formLogin()
                    .loginPage("/login/page")// 交给 /login/page 响应认证(登录)页面
                    .loginProcessingUrl("/login/form")  // 登录表单提交处理Url, 默认是 /login
                    .usernameParameter("name") // 默认用户名的属性名是 username
                    .passwordParameter("pwd") // 默认密码的属性名是 password
                    .and()
                    .authorizeRequests()//认证请求
                    .antMatchers("/login/page").permitAll()//自定义登录页不需要认证
                    .anyRequest().authenticated();// 所有进入应用的HTTP请求都要进行认证*/
    
    
            http.formLogin()
                    .loginPage(securityProperties.getLoginPage())// 交给 /login/page 响应认证(登录)页面
                    .loginProcessingUrl(securityProperties.getLoginProcessingUrl())  // 登录表单提交处理Url, 默认是 /login
                    .usernameParameter(securityProperties.getUsernameParameter()) // 默认用户名的属性名是 username
                    .passwordParameter(securityProperties.getPasswordParameter()) // 默认密码的属性名是 password
                    .and()
                    .authorizeRequests()//认证请求
                    .antMatchers(securityProperties.getLoginPage()).permitAll()//自定义登录页不需要认证
                    .anyRequest().authenticated();// 所有进入应用的HTTP请求都要进行认证
        }
    
        /**
         * 放行静态资源(js css 等)
         *
         * @param web
         */
        @Override
        public void configure(WebSecurity web) {
            //web.ignoring().antMatchers("/dist/**", "/modules/**", "/plugins/**");
            web.ignoring().antMatchers(securityProperties.getStaticPaths());
        }
    }
     
     
  • 相关阅读:
    自定义Filter服务
    filter 以及 orderBy的使用
    ng-repeat-start ng-repeat-end 的使用
    ng-repeat 与ng-switch的简单应用
    ng-bind-html 的使用
    Oracle instr用法
    Oracle left查询案例
    Oracle case用法
    mysql 导出导入sql
    Gson解析复杂JSON对象
  • 原文地址:https://www.cnblogs.com/yscec/p/14153017.html
Copyright © 2020-2023  润新知