1.oauth2的密码模式基础使用可以查看Spring cloud Oauth2的密码模式内存方式实现登录授权验证
2.在项目中oauth2的密码模式实现授权都是直接读取数据库的用户信息进行验证的。
oauth2-server: 认证中心,提供token的生成,刷新,认证功能。
oauth2-client: 客户端服务,调用接口会去认证中心验证token一致性。
3.代码实现:
在Spring cloud Oauth2的密码模式内存方式实现登录授权验证的基础代码上进行更改。
3.1 oauth2-server修改部分:
yml添加数据库配置:
spring: application: name: oauth2-server redis: database: 2 host: localhost password: 123456 jedis: pool: max-active: 8 max-idle: 8 min-idle: 0 timeout: 100ms datasource: url: jdbc:mysql://127.0.0.1:3306/spring_cloud?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false username: root password: 123456 hikari: connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000 maximum-pool-size: 9 server: port: 8001 management: endpoint: health: enabled: true mybatis: typeAliasesPackage: com.cxh.oauth2service.entity mapperLocations: classpath*:/mapper/*.xml
oauth2配置采用数据库方式
@Configuration @EnableAuthorizationServer public class OAuth2Config extends AuthorizationServerConfigurerAdapter { @Autowired public PasswordEncoder passwordEncoder; @Autowired public UserDetailsService cxhUserDetailsService; @Autowired private AuthenticationManager authenticationManager; @Autowired private TokenStore redisTokenStore; @Autowired private DataSource dataSource; @Override public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception { /** * redis token 方式 */ endpoints.authenticationManager(authenticationManager) .userDetailsService(cxhUserDetailsService) .tokenStore(redisTokenStore); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { JdbcClientDetailsServiceBuilder jcsb = clients.jdbc(dataSource); jcsb.passwordEncoder(passwordEncoder); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.allowFormAuthenticationForClients(); security.checkTokenAccess("isAuthenticated()"); security.tokenKeyAccess("isAuthenticated()"); } }
登录时验证授权直接读取数据库数据
@Slf4j @Component(value = "cxhUserDetailsService") public class CxhUserDetailsService implements UserDetailsService { @Autowired private PasswordEncoder passwordEncoder; @Autowired private UserInfoService userInfoService; @Autowired private SysRoleService sysRoleService; @Autowired private PermissionService permissionService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserInfo userInfo = userInfoService.getByUsername(username); if(userInfo == null){ throw new UsernameNotFoundException("不存在当前用户"); } List<SysRole> sysRoleList = sysRoleService.listByUserId(userInfo.getId()); List<SimpleGrantedAuthority> authorities = new ArrayList<>(); sysRoleList.forEach(e -> authorities.add(new SimpleGrantedAuthority(e.getCode()))); List<Permission> permissionList = permissionService.listByUserId(userInfo.getId()); permissionList.forEach(e -> authorities.add(new SimpleGrantedAuthority(e.getCode()))); //密码是加密的 //String password = passwordEncoder.encode("123456"); String password = userInfo.getPassword(); return new org.springframework.security.core.userdetails.User(username,password, authorities); } }
3.2 oauth2-client 可以不用修改,直接运行。
这里调整了控制器的一些请求:
@Slf4j @RestController public class TestController { //返回true @GetMapping(value = "get") @PreAuthorize("hasRole('ROLE_TEST')") public Object get(Authentication authentication){ return "权限测试1"; } //返回false @GetMapping(value = "get2") @PreAuthorize("hasRole('role_test')") public Object get2(Authentication authentication){ return "权限测试2"; } //返回true @GetMapping(value = "get3") @PreAuthorize("hasRole('TEST')") public Object get3(Authentication authentication){ return "权限测试3"; } //返回false @GetMapping(value = "get4") @PreAuthorize("hasRole('test')") public Object get4(Authentication authentication){ return "权限测试4"; } //返回true @GetMapping(value = "get5") @PreAuthorize("hasAnyRole('ROLE_TEST')") public Object get5(Authentication authentication){ return "权限测试5"; } //返回false @GetMapping(value = "get6") @PreAuthorize("hasAnyRole('role_test')") public Object get6(Authentication authentication){ return "权限测试6"; } //返回true @GetMapping(value = "get7") @PreAuthorize("hasAnyRole('TEST')") public Object get7(Authentication authentication){ return "权限测试7"; } //返回false @GetMapping(value = "get8") @PreAuthorize("hasAnyRole('test')") public Object get8(Authentication authentication){ return "权限测试8"; } //返回true @GetMapping(value = "get9") @PreAuthorize("hasAnyAuthority('ROLE_TEST')") public Object get9(Authentication authentication){ return "权限测试9"; } //返回false @GetMapping(value = "get10") @PreAuthorize("hasAnyAuthority('role_test')") public Object get10(Authentication authentication){ return "权限测试10"; } //返回false @GetMapping(value = "get11") @PreAuthorize("hasAnyAuthority('TEST')") public Object get11(Authentication authentication){ return "权限测试11"; } //返回false @GetMapping(value = "get12") @PreAuthorize("hasAnyAuthority('test')") public Object get12(Authentication authentication){ return "权限测试12"; } }
4.数据库:
创建数据表数据:
user_info中的用户password是用passwordEncoder.encode("password");进行加密保存。
oauth_client_details表中的 client_secret 字段不能直接是 secret 的原始值,需要经过加密。因为是用的 BCryptPasswordEncoder,所以最终插入的值是经过 BCryptPasswordEncoder.encode()之后的值。
5.oauth2-service, oauth2-client项目运行后效果:
6.demo下载