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());
    }
}
 
 
原文地址:https://www.cnblogs.com/yscec/p/14153017.html