表单认证方式 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://gitee.com/zhechaochao/security-parent.git