Spring security 02-自定义用户登录页面和登录处理逻辑

Spring security 系列博客目录

对应源代码

开篇

上一篇(在项目里面引入spring-security会发生什么)我们将 Spring-seccurity 引入到了我们的spring-boot工程中,没有做多余的配置,spring-security 就已经默认帮我们配置了一个拦截器,应用启动后,当我们访问应用提供的资源时,都会跳转到 security 为我们提供的一个默认登陆页,当我们输入security为我们提供的用户名和密码,登陆成功后,就可以获取我们需要的资源。那么问题来了!我们如何自定义自己的登录页面,以及使用我们自己的用户信息去登录呢?

实战

创建工程

为了不影响之前的版本,我们这里新建一个模块 spring-security-02,之前的版本是spring-security-01. https://github.com/nimo10050/spring-security-sample/tree/master/spring-security-02

引入依赖

依赖跟上个版本一样,如下:

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

	</dependencies>

新建 SpringSecurity 配置类

既然我们需要自定义一些东西,只能通过额外配置的方式来实现。所以这里引入了spring-security的配置类

  • 添加 @Component注解

  • 添加 Spring-security 的注解 EnableWebSecurity 标记这是 security的 配置类

  • 继承 WebSecurityConfigurerAdapter 重写它的配置方法

  • 重写 configure(HttpSecurity http) 方法是为了定义登陆页

  • 重写 configure(AuthenticationManagerBuilder auth) 是为了定义登录逻辑

      package com.example.demo.config;
    
      import com.example.demo.config.service.UserDetailServiceImpl;
      import org.springframework.context.annotation.Bean;
      import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
      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.UserDetailsService;
      import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
      import org.springframework.security.crypto.password.PasswordEncoder;
      import org.springframework.stereotype.Component;
    
      [@Component](https://my.oschina.net/u/3907912)
      @EnableWebSecurity
      public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
      [@Override](https://my.oschina.net/u/1162528)
      protected void configure(HttpSecurity http) throws Exception {
    
      	http.csrf().disable();// 必须有, 不然会 403 forbidden
    
      	http.formLogin()
      			.loginPage("/loginPage.html")// 自定义登录页
      			.loginProcessingUrl("/form/login");// 自定义登录 action, 名字随便起
      			// passwordParameter("password") 配置 form 表单 密码的 name 属性值
      			// usernameParameter("username") 配置 form 表单 用户名的 name 属性值
    
      	// 访问 "/form/login", "/loginPage.html"   放行
      	http.authorizeRequests().antMatchers("/form/login", "/loginPage.html").permitAll()
      			.anyRequest().authenticated();
      }
    
      /**
       * 配置 用户登录处理类
       *
       * [@param](https://my.oschina.net/u/2303379) auth
       * @throws Exception
       */
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      	/* 将用户信息存储到内存中
      	   实际上不会这样做,了解下即可
      	auth.inMemoryAuthentication()
      			.withUser("zhangsan")
      			.password(passwordEncoder().encode("123456"))
      			.authorities("admin");*/
    
      	auth.userDetailsService(userDetailsService());
      }
    
      /**
       * 自定义登录处理
       *
       * @return
       */
      @Bean
      public UserDetailsService userDetailsService() {
      	return new UserDetailServiceImpl();
      }
    
    
      /**
       * 加密工具
       * 2.x 版本的 spring-security-starter 必须加上
       *
       * @return
       */
      @Bean
      public PasswordEncoder passwordEncoder() {
      	return new BCryptPasswordEncoder();
      }
    
      }
    

UserDetailService 接口

通过重写 UserDetailService 接口的 loadUserByUsername方法来实现登录逻辑,在loadUserByUsername 方法里我们可以读取数据库或者其他存储介质,来校验我们的用户是否存在。最后将我们实现的类配置到config方法中。

/**
 * 自定义登录处理逻辑
 */
public class UserDetailServiceImpl implements UserDetailsService {

/*    @Autowired
private PasswordEncoder passwordEncoder;*/

/**
 * @param username 登录页面输入的用户名
 * @return
 * @throws UsernameNotFoundException
 */
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    // TODO 根据 username 去用户表查询出来用户的信息,然后进行验证

    // 验证成功后,返回Spring-Security 提供的 User 对象
    // 对应三个构造参数依次是: 1.用户名 2.密码(经过 passwordEncoder 加密后的密码) 3.权限列表
    return new User(username, "$2a$10$g1gzj4KvMNY1kMZT1xDx9ufLuaDvCFDpX.PdETx85zQwXI/Mn4ttC", AuthorityUtils.createAuthorityList("admin"));
}

public static void main(String[] args) {
    System.out.println(new BCryptPasswordEncoder().encode("123456"));// $2a$10$g1gzj4KvMNY1kMZT1xDx9ufLuaDvCFDpX.PdETx85zQwXI/Mn4ttC
}
}

其他需要注意的点

  • 在 configure(HttpSecurity http) 方法中需要加上 http.csrf().disable();不用问为什么,加上就完事了。
  • 当我们重写了config 方法后,spring-security 就不会拦截我们要访问的资源了,所以需要重新配置下

http.authorizeRequests().antMatchers("/form/login","/loginPage.html").permitAll().anyRequest().authenticated();

  • 当我们定义了UserDetailService,应用启动时控制台就不会打印默认密码了。

  • 高版本的 security 必须要配置密码加密工具类。不然会报错

      passwordEncoder is null
    

总结

spring-security 提供的功能特别多,我们需要选择性地去使用 security 提供的 api,然后去定制我们的需求。一步一步来,不要盲目地把别人写好的案例拷贝到自己的项目中,一个成型的案例,里面的配置往往都是一大堆,根本无从看起(我刚开始就是这样,把别人的security案例中的每个方法,每个api都扣一遍,很费时间),英文官方文档能看个大概(要怪自己阅读文档能力不够),看了无数的相关博客,每一篇博客大概只有十分之一是我想要的。最后把这些知识碎片组合在一起,经过自己编码实现,才有这一系列入门踩坑博客。希望能帮助有需要的人。

转载于:https://my.oschina.net/u/3984985/blog/3089853

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security中,可以使用以下方式自定义登录页面: 1. 创建一个自定义登录页面。 2. 配置Spring Security,指定自定义登录页面的位置,绑定登录请求处理逻辑。 3. 配置Spring MVC,指定自定义登录页面的路径。 以下是具体实现步骤: 1. 创建一个自定义登录页面。 在Spring MVC项目的Web根目录下创建一个login.jsp页面。 在页面中提供用户名和密码输入框,并使用POST方式将表单提交到 /login 请求上。 2. 配置Spring Security,指定自定义登录页面的位置,绑定登录请求处理逻辑。 在Spring Security配置文件中,使用formLogin()方法指定自定义登录页面的位置。 并使用loginProcessingUrl()方法绑定登录请求处理逻辑,该方法指定登录请求的URL路径。 最后,使用loginPage()方法指定登录页面URL路径,该方法会重定向到自定义登录页面。 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginProcessingUrl("/login") // 指定登录请求的URL .loginPage("/custom-login") // 指定登录页面URL .permitAll(); } } 3. 配置Spring MVC,指定自定义登录页面的路径。 在Spring MVC配置文件中,配置视图解析器,指定自定义登录页面的路径。 @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); return viewResolver; } 当用户访问应用程序的任何受保护的URL时,由Spring Security拦截请求并跳转到自定义登录页面用户登录页面输入用户名和密码后,表单将被POST提交到指定的loginProcessingUrl上。Spring Security将验证用户的凭据,并根据验证结果决定是否授权用户访问请求的资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值