Oauth2 整合 SpringSecurity
Oauth2
这里采用了 Oauth2 的 code 模式 , Oauth2
- Oauth的大致思路是一个线性的流程。
第三方应用向资源持有者请求获取资源
资源持有者授权给予第三方应用一个许可
第三方应用将该许可给予认证服务器进行认证,如果认证成功,返回一个Access Token
第三方应用使用该access token到资源服务器处获取该access token对应的资源(也就是第一步中资源持有者自身的资源)
整合 Oauth2 和 SpringSecurity
1. 导入相应的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- oauth2 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<!-- 使用dependencies来管理spring cloud 版本 -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
2. WebSecurityConfig
这里 通过userDetailsService 来创建用户
文件路径如下 , 连接数据库等代码省略
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true , securedEnabled = true , jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
BCryptPasswordEncoder passwordEncoder;
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 使用userDetailsService来创建用户 ,方便整合数据库 , 将用户的账号密码保存在数据库
auth.userDetailsService(userDetailsService);
// 自定义用户的方式
// inMemoryAuthentication()
// .withUser("admin").password(passwordEncoder.encode("123456")).roles("ADMIN")
// .and()
// .withUser("user").password(passwordEncoder.encode("123456")).roles("USER");
}
}
UserDetailsServiceImpl
这个类用来获取数据库中的用户信息 并保存相应的权限
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
TbUserService userService;
@Autowired
TbPermissionService permissionService;
/**
* 查询数据库用户信息
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
TbUser tbUser = userService.getUserByUserName(username);
if (tbUser == null){
throw new UsernameNotFoundException("username: "+username + "is not exist!");
}
List<GrantedAuthority> authorities = new ArrayList<>();
List<TbPermission> permissions = permissionService.getByUserId(tbUser.getId());
// 遍历权限并添加
permissions.forEach(tbPermission -> {
authorities.add(new SimpleGrantedAuthority(tbPermission.getEname()));
});
return new User(tbUser.getUsername(), tbUser.getPassword(), authorities);
}
}
AuthConfig
@EnableAuthorizationServer
@Configuration
public class AuthConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
public DataSource dataSource;
@Bean
public TokenStore tokenStore(){return new JdbcTokenStore(dataSource);
}
@Bean
public BCryptPasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
@Bean
public ClientDetailsService jdbcClientDetailsService(){return new JdbcClientDetailsService(dataSource);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
// 客户端账号密码
.withClient("client")
.secret(passwordEncoder().encode("123456"))
// 授权类型
.authorizedGrantTypes("authorization_code")
.scopes("app")
// 重定向地址
.redirectUris("https://www.baidu.com");
// 从数据库中获取 client 对象
// clients.withClientDetails(jdbcClientDetailsService());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore());
}
}
使用 http://localhost:9000/oauth/authorize?client_id=client&response_type=code
访问
会在重定向地址中携带code
同过postman 发送请求 并且携带 code 就可以获得token了
源码地址:源码地址