springsecurity和oauth2的概念都很熟悉了,不在这里细说,本次主要记录一下整合的过程
先看一下整个代码的结构
一、先创建一个项目,并整合mybatis-plus因为整合mybatis-plus不是本次记录的重点,所以过程省略,可以参考:
springboot整合mybatis-plus
二、整合springsecurity+oauth2 1、导入springsecurity和oauth依赖
org.springframework.cloud
spring-cloud-starter-oauth2
org.springframework.cloud
spring-cloud-starter-security
因为是用的cloud的依赖,要添加cloud
2、引入依赖后,先创建2个controller,方便后续测试org.springframework.cloud spring-cloud-dependenciesGreenwich.SR3 pom import
UserController,/user
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/getUserInfo")
public Object getUserInfo(Authentication authentication){
return authentication.getPrincipal();
}
}
TestController,/test
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/getStr")
public String getStr(){
return "test";
}
}
因为要使用springsecurity的认证,要配置springsecurity相关的配置3、自定义用户配置类,实现UserDetails
public class CustomUserDetails implements UserDetails {
private String username;
private String password;
private List authorities;
// 构造方法
public CustomUserDetails(String username, String password, List authorities) {
this.username = username;
this.password = password;
this.authorities = authorities;
}
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
4、自定义登录认证的逻辑
这里的登录,是用户授权的时候需要登录的。先登录认证之后,才能给请求授权
这里为了方便,没有从数据库取用户,直接代码中写死,用admin登录,密码:123456
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//实际是根据用户名去数据库查,这里就直接用静态数据了
if(!username.equals("admin")) {
throw new UsernameNotFoundException("用户名不存在!");
}
// 密码加密
String password = passwordEncoder.encode("123456");
//创建User用户,自定义的User
CustomUserDetails user = new CustomUserDetails(username,password, AuthorityUtils.
commaSeparatedStringToAuthorityList("admin"));
return user;
}
}
5、配置springsecurity配置类
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.authorizeRequests()
.antMatchers("/oauth
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()//内存中
.withClient("client")//客户端ID
.secret(passwordEncoder.encode("111111"))//秘钥
.redirectUris("https://www.baidu.com")//重定向到的地址
.scopes("all")//授权范围
.autoApprove(true)//自动授权,返回验证码
.authorizedGrantTypes("authorization_code","password");//授权类型
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
//密码模式需要配置(可能是因为直接根据用户名密码登录)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsServiceImpl);
}
}
7、配置资源服务器
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.requestMatchers()
.antMatchers("/user
@Bean
public TokenStore redisTokenStore(){
RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
redisTokenStore.setPrefix("oauth-token:");
return redisTokenStore;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
//密码模式需要配置(可能是因为直接根据用户名密码登录)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsServiceImpl)
.tokenStore(redisTokenStore());
}
3、此时访问接口获取令牌,使用redis可视化工具,可以看到token的值
普通的token太短,不太安全,下面使用jwt来生成token五、整合jwt 1、创建配置类JwtTokenStoreConfig
@Configuration
public class JwtTokenStoreConfig {
//JwtAccessTokenConverter
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey("test");//设置签名秘钥
return jwtAccessTokenConverter;
}
@Bean("jwtTokenStore")
public TokenStore jwtTokenStore(){
JwtTokenStore jwtTokenStore = new JwtTokenStore(jwtAccessTokenConverter());
return jwtTokenStore;
}
}
2、注释掉认证服务配置AuthorizationServerConfig中,注册的TokenStore
// @Bean
// public TokenStore redisTokenStore(){
// RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
// redisTokenStore.setPrefix("oauth-token:");
// return redisTokenStore;
// }
3、认证服务器配置类,添加代码:
@Autowired
@Qualifier("jwtTokenStore")
TokenStore jwtTokenStore;
@Autowired
JwtAccessTokenConverter jwtAccessTokenConverter;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
//密码模式需要配置(可能是因为直接根据用户名密码登录)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsServiceImpl)
// .tokenStore(redisTokenStore())//设置为redis存储
.tokenStore(jwtTokenStore)//设置为jwt存储
.accessTokenConverter(jwtAccessTokenConverter)
;
}
4、此时获取的token,就是jwt格式的token
上面代码,客户端是写死在代码中的,加入要添加客户端,还要去改代码六、使用数据库保存客户端 1、添加数据源配置类 DataSourceConfig
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
@Data
public class DataSourceConfig {
private String url;
private String username;
private String password;
@Bean(name = "oauth2DataSource")
public DataSource getOauth2DataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);// 用户名
dataSource.setPassword(password);// 密码
return dataSource;
}
}
2、修改认证服务器的配置,添加如下代码:
@Autowired
@Qualifier("oauth2DataSource")
private DataSource dataSource;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
// 注释掉原来的配置
// clients.inMemory()//内存中
// .withClient("client")//客户端ID
// .secret(passwordEncoder.encode("111111"))//秘钥
// .redirectUris("https://www.baidu.com")//重定向到的地址
// .scopes("all")//授权范围
// .autoApprove(true)//自动授权,返回验证码
// .authorizedGrantTypes("authorization_code","password","refresh_token");//授权类型
}
3、添加表oauth_client_details
CREATE TABLE `oauth_client_details` ( `client_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `resource_ids` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `client_secret` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `scope` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `authorized_grant_types` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `web_server_redirect_uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `authorities` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `access_token_validity` int(11) DEFAULT NULL, `refresh_token_validity` int(11) DEFAULT NULL, `additional_information` text CHARACTER SET utf8 COLLATE utf8_general_ci, `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, `trusted` tinyint(1) DEFAULT 0, `autoapprove` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT 'false', PRIMARY KEY (`client_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
并添加数据如下:
注意:秘钥是经过加密的
4、此时重启项目,获取token的时候,如果客户端id或者秘钥不正确,或报错


