【微服务|Spring Security⑮】spring security自定义认证

Spring Security提供了非常好的认证扩展方法,比如:将用户信息存储到内存中,实际开发中用户信息通常在数据库,Spring Security可以实现从数据库读取用户信息,Spring security还支持多种授权方法。

4.3.1 自定义登录页面

Spring Security的默认配置没有明确设定一个登录页面的URL ,因此Spring Security会根据启用的功能自动生成一个登录页面URL ,并使用默认URL处理登录的提交内容,登录后跳转的到默认URL等等。尽管自动生成的登录页面很方便快速启动和运行,但大多数应用程序都希望定义自己的登录页面。

4.3.1.1 认证页面

将security-springmvc工程的login.jsp拷贝到security-springboot下,目录保持一致。

在这里插入代码片
4.3.1.2 配置认证页面

在WebConfig.java中配置认证页面地址:

//默认Url根路径剧阵专至Ij/login ,此url为spring security提供
@0verride
public void addViewControllers(ViewControllerRegistry registry) {
    
    
		registry.addViewController("/").setViewName("login-view")
  		registry.addViewController("login-view").setViewName("login");
}
4.3.1.3 安全配置

在WebSecurityConfig中配置表单登录信息:


(1)允许表单登录
(2 )指定我们自己的登录页,spring security以重定向方式将路径转发到/login-view
(3)指定登录处理的URL ,也就是用户名、密码表单提交的目的路径
(4)指定登录成功后的跳转URL
(5 )我们必须允许所有用户访问我们的登录页(例如为验证的用户),这个formLogin() .permitAll()方法允许任意用户访问基于表单登录的所有的URL。

4.3.1.4 测试

当用户没有认证时访问系统的资源会重定向到login-view页面

在这里插入代码片

输入账号和密码,点击登录,报错:

在这里插入代码片

问题解决:

spring security为防止CSRF ( Cross-site request forgery跨站请求伪造)的发生,限制了除了get以外的大多数方 法。

解决方法1:

屏蔽CSRF控制,即spring security不再限制CSRF。
配置 WebSecurityConfig

@0verride
protected void configure(HttpSecurity http) throws Exception {
    
    
 	 http.csrf().disable()//屏蔽CSRF控制,即 spring security 不再限制CSRF
}

解决办法2 :

在login.jsp页面添加一个token , spring security会验证token ,如果token合法则可以继续请求。
修改 login.jsp

<form action="login" method="post">
	<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>

4.3.2 连接数据库认证

前边的例子我们是将用户信息存储在内存中,实际项目中用户信息存储在数据库中。根据前边对认证流程研究,只需要重新定义UserDetailService即可实现根据用户账号查询数据库。

4.3.2.1 创建数据库

创建user_db数据库

CREATE DATABASE ‘user_db’ CHARACTER SET 'utf8‘ COLLATE ‘utf8_general_ci’;

创建t_user 表

CREATE TABLE 't_user' (
	'id' bigint(20) NOT NULL COMMENT,用户id',
	'username' varchar(64) NOT NULL,
	'password' varchar(64) NOT NULL,
	'fullname' varchar(255) NOT NULL COMMENT,用户姓名',
	'mobile' varchar(ll) DEFAULT NULL COMMENT,手机号
	PRIMARY KEY ('id') USING BTREE
)ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
4.3.2.2 代码实现

1 )定义dataSource
在application.properties 配置

spring.datasource.url=jdbc:mysql://localhost:3306/user_db
spring.datasource.username=root
spring.datasource.password=mysql
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

2)添加依赖

<dependency>
	<groupld>org.springframework.boot</groupld>
	<artifactld>spring-boot-starter-test</artifactld>
	<scope>test</scope>
</dependency>
<dependency>
	<groupld>org.springframework.boot</groupld>
	<artifactld>spring-boot-starter-jdbc</artifactld>
</dependency>
<dependency>
	<groupld>mysql</groupld>
	<artifactld>mysql-connector-java</artifactld>
	<version>5.1.47</version>
</dependency>

3 )定义Dao

定义模型类型,在model包定义UserDto:

@Data
public class UserDto {
    
     private String id;
	private String username;
	private String password;
	private String fullname;
	private String mobile;
}

在Dao包定义UserDao :

@Repository
public class UserDao {
    
    
	@Autowired
	ZJdbcTemplate jdbcTemplate;
	public UserDto getUserByUsername(String username){
    
    
		String sql =r,select id,username,password,funname from t_user where username = ?";
		List<UserDto> list = jdbcTemplate.query(sqlj new Object[Jlusername}^ new BeanPropertyRowMappero(UserDto. class));
		if(list == null && list.size() <= 0)(
			return null;
		}
		return list.get(0);
	}
}
4.3.2.3 定义 UserDetailService

在service包下定义SpringDatallserDetailsService :

@Service
public class SpringDatallserDetailsService implements UserDetailsService {
    
    
		@Autowired
		UserDao userDao;
		
		@Override
		public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
    
			//登录账号
			System.out. println();
			
			//根据账号去数据库查询...
			UserDto user = userDao.getUserByUsername(username);
			
			if(user == null){
    
    
				return null;
			}
			//这里暂时使用静态麴居
			UserDetails userDetails =User.withUsername(user.getFullname()).password(user.getPassword()).authorities("pl").build(); 
			return userDetails;
		}
}
4.3.2.3 测试

输入账号和密码请求认证,跟踪代码。

4.3.2.4 使用BCryptPasswordEncoder

按照我们前边讲的PasswordEncoder的使用方法,使用BCryptPasswordEncoder需要完成如下工作:

1、在安全配置类中定义BCryptPasswordEncoder

@Bean
public PasswordEncoder passwordEncoder() {
    
    
	return new BCryptPasswordEncoder();
}

2、UserDetails中的密码存储BCrypt格式

前边实现了从数据库查询用户信息,所以数据库中的密码应该存储BCrypt格式

package com.uncle.seciruty.springboot.util;

import org.springframework.security.crypto.bcrypt.BCrypt;

/**
 * @program: spring-boot-security
 * @description:
 * @author: 步尔斯特
 * @create: 2021-08-06 22:12
 */
public class BCryptUtil {
    
    
    public static void main(String[] args) {
    
    
        String hashpw = BCrypt.hashpw("456", BCrypt.gensalt());
        System.out.println(hashpw);

        boolean checkpw = BCrypt.checkpw("456","$2a$10$bcJXXryMCxXtkxRkG1UekOkOe0BqxiqOYKJzGni64jnyWAD15wmDy");
        System.out.println(checkpw);

        //123 -> $2a$10$8iHn2TEvyzkUgO2np9glzufe.wtRyjA5u3xfvs/D.9FCzm1XvCAGm
        //456 -> $2a$10$bcJXXryMCxXtkxRkG1UekOkOe0BqxiqOYKJzGni64jnyWAD15wmDy

    }
}

```**加粗样式**

猜你喜欢

转载自blog.csdn.net/CSDN_SAVIOR/article/details/125683340