spring boot 之 security(一) 配置
2019-10-12 本文已影响0人
_大叔_
我这里使用的是多项目搭建,we和app是分开的
项目结构
项目结构一、先引入依赖
core 中的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<!-- 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 第三方对接 依赖包QQ,微信等 -->
<!-- 提供Java 配置 -->
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-config</artifactId>
<version>1.1.4.RELEASE</version>
</dependency>
<!-- 提供社交连接框架和OAuth 客户端支持 -->
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-core</artifactId>
<version>1.1.4.RELEASE</version>
</dependency>
<!-- 提供社交安全支持 -->
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-security</artifactId>
<version>1.1.4.RELEASE</version>
</dependency>
<!-- 管理web应用程序的连接 -->
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-web</artifactId>
<version>1.1.4.RELEASE</version>
</dependency>
<!-- oauth2协议 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
web 中的依赖
<dependency>
<groupId>com.wt</groupId>
<artifactId>security-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
app 中的依赖
<dependency>
<groupId>com.wt</groupId>
<artifactId>security-core</artifactId>
<version>${project.version}</version>
</dependency>
demo 中的依赖
<dependency>
<groupId>com.wt</groupId>
<artifactId>security-web</artifactId>
<version>${project-version}</version>
</dependency>
二、配置文件
demo 中的配置
server:
port: 9203
# jdbc_config datasource
spring:
application:
name: security-demo
# 指定session集群的存储,启动之前这里先设置none要不然redis和jdbc会报覆盖类错误。
session:
store-type: none
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.15.128:3306/cloud?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull
username: root
password: password
# Hikari will use the above plus the following to setup connection pooling
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 5
maximum-pool-size: 15
auto-commit: true
idle-timeout: 30000
pool-name: DatebookHikariCP
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
# redis:
# database: 0
# host: 192.168.15.128
# port: 6379
# password:
# lettuce:
# pool:
# max-active: 20
# timeout: 5000
三、security中的核心及原理
核心过滤器spring security 最主要的核心就是过滤器,他先会从 绿色 部分开始执行,到 橘色 进行校验,如果校验失败,则会返回到 蓝色Exception 部分。
以上图中的这几个Filter大家可以在idea中找到并得到源码,执行最简单的debug来查看。
若想要 UsernamePasswordAuthenticationFilter 生效,则需要一个类继承WebSecurityConfigurerAdapter 并重写configure(HttpSecurity http),否则走默认配置(Basic)。
配置WebSecurityConfigurerAdapter
四、简单定制自己的身份认证
一开始默认的是spring自己的身份认证,在启动后控制台会给一个密码用于最基本的登陆认证,如果我想自定义一个账号密码怎么办?接下来介绍的是 UserDetailsService,这是spring自带的负责用户信息获取的一个接口,我们只要重写 loadUserByUsername 这个方法即可。
package com.wt.cloud.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.*;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
@Slf4j
/**
* 功能描述: UserDetailsService负责用户信息获取逻辑
* @author : big uncle
* @date : 2019/10/11 15:21
*/
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
log.info("登陆用户名称:{}",s);
String password = "123456";
log.info("获得密码:{}",password);
// UserDetails 处理用户校验逻辑
UserDetails userDetails = User.builder()
.username(s)
// 当你在密码123456上使用了前缀{noop} 意味着你的密码不使用加密
.password(password)
// 解码
.passwordEncoder((str) -> "{bcrypt}" + new BCryptPasswordEncoder().encode(str))
// // 账号是否过期 如果帐户已过期,则为true,否则为false
.accountExpired(false)
// // 账号是否被锁 如果帐户已锁定,则为true,否则为false
.accountLocked(false)
// // 账号是否可用 如果帐户被禁用,则为true,否则为false
.disabled(false)
// // 凭证是否过期 如果凭据已过期,则为true,否则为false
.credentialsExpired(false)
// 权限
.authorities( AuthorityUtils.commaSeparatedStringToAuthorityList("admin"))
.build();
return userDetails;
}
/**
* 功能描述: 列出所有的加密方式
* @author : big uncle
* @date : 2019/10/12 0:11
*/
public static Map<String,PasswordEncoder> encoders(){
return new HashMap<String,PasswordEncoder>(){{
put("bcrypt", new BCryptPasswordEncoder());
// 不做加密
put("noop", NoOpPasswordEncoder.getInstance());
put("pbkdf2", new Pbkdf2PasswordEncoder());
put("scrypt", new SCryptPasswordEncoder());
put("sha256", new StandardPasswordEncoder());
}};
}
}
或把加密方式写到配置里
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Slf4j
@Component
public class MyUserDetails implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
log.debug("登陆账号是 {}",s);
String password = "123455";
String newPassword = passwordEncoder.encode(password);
log.debug("加密后的密码是 {}",newPassword);
return new User(s,newPassword,true,true,true,true, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}