SpringOauth2简单登陆

傷城~ 2023-05-31 12:11 80阅读 0赞

SpringOauth2实现Jdbc简单认证登陆

创建一个SpringBoot工程
依赖如下:

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>1.5.10.RELEASE</version>
  5. <relativePath /> <!-- lookup parent from repository -->
  6. </parent>
  7. <properties>
  8. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  9. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  10. <java.version>1.8</java.version>
  11. </properties>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-security</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-web</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.security.oauth</groupId>
  23. <artifactId>spring-security-oauth2</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter-data-jpa</artifactId>
  28. </dependency>
  29. <dependency>
  30. <groupId>mysql</groupId>
  31. <artifactId>mysql-connector-java</artifactId>
  32. <version>8.0.16</version>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-starter-test</artifactId>
  37. <scope>test</scope>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework.security</groupId>
  41. <artifactId>spring-security-test</artifactId>
  42. <scope>test</scope>
  43. </dependency>
  44. </dependencies>

这里主要依赖的是Spring Security 、Spring Security Oauth2 依赖,创建好项目后我们创建一个User类并且实现UserDetail接口如下:

  1. public class UserInfo implements UserDetails{
  2. private String name;
  3. private String email;
  4. private String password;
  5. public void setPassword(String password) {
  6. this.password = password;
  7. }
  8. public String getName() {
  9. return name;
  10. }
  11. public void setName(String name) {
  12. this.name = name;
  13. }
  14. public String getEmail() {
  15. return email;
  16. }
  17. public void setEmail(String email) {
  18. this.email = email;
  19. }
  20. @Transient
  21. private List<GrantedAuthority> authorityList;
  22. public List<GrantedAuthority> getAuthorityList() {
  23. return authorityList;
  24. }
  25. public void setAuthorityList(List<GrantedAuthority> authorityList) {
  26. this.authorityList = authorityList;
  27. }
  28. @Override
  29. public Collection<? extends GrantedAuthority> getAuthorities() {
  30. return authorityList;
  31. }
  32. @Override
  33. public String getPassword() {
  34. return password;
  35. }
  36. @Override
  37. public String getUsername() {
  38. return name;
  39. }
  40. @Override
  41. public boolean isAccountNonExpired() {
  42. return true;
  43. }
  44. @Override
  45. public boolean isAccountNonLocked() {
  46. return true;
  47. }
  48. @Override
  49. public boolean isCredentialsNonExpired() {
  50. return true;
  51. }
  52. @Override
  53. public boolean isEnabled() {
  54. return true;
  55. }
  56. @Override
  57. public String toString() {
  58. return "UserInfo{" +
  59. "name='" + name + '\'' +
  60. ", email='" + email + '\'' +
  61. ", password='" + password + '\'' +
  62. ", authorityList=" + authorityList +
  63. '}';
  64. }
  65. }

这里UserDetail接口我就不多解释了,这几个方法大家都应该很清楚,然后我们创建一个CustomerUserService去实现UserDetailsService接口的loadUserByUsername方法:

  1. @Service
  2. public class CustomerUserService implements UserDetailsService {
  3. private Logger log = LoggerFactory.getLogger(this.getClass());
  4. @Override
  5. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  6. UserInfo user = new UserInfo();
  7. user.setName(username);
  8. user.setPassword("123456");
  9. log.info("username ->" + username);
  10. if (user.getName().equals("zhoubiao")) {
  11. List<GrantedAuthority> auths = new ArrayList<>();
  12. auths.add(new SimpleGrantedAuthority("ROLE_USER"));
  13. user.setAuthorityList(auths);
  14. log.info("user ->" + user);
  15. return user;
  16. }
  17. return null;
  18. }
  19. }

这里的代码很简单。这里的角色权限都是写死的。不管是用mybatis的mapper还是spring data jpa 都可以通过注入到这里来进行查询操作。这里为了简化操作。我就写死了。

然后我们创建我们的授权服务器:

  1. @Configuration
  2. @EnableAuthorizationServer
  3. public class OAuth2AuthorizationServer extends
  4. AuthorizationServerConfigurerAdapter {
  5. @Resource
  6. private DataSource dataSource;
  7. @Bean
  8. public ClientDetailsService clientDetailsService() {
  9. return new JdbcClientDetailsService(dataSource);
  10. }
  11. @Override
  12. public void configure(ClientDetailsServiceConfigurer clients)
  13. throws Exception {
  14. clients.jdbc(dataSource);
  15. }

注意这里的DataSource是依赖Spring Data Jpa 中为我们封装的Spring Jdbc的相关配置依赖。

下面就是我们的资源服务器配置了如下:

  1. @Configuration
  2. @EnableResourceServer
  3. public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter {
  4. @Override
  5. public void configure(HttpSecurity http) throws Exception {
  6. http.authorizeRequests()
  7. .anyRequest()
  8. .authenticated()
  9. .and()
  10. .requestMatchers()
  11. .antMatchers("/api/**");
  12. }
  13. }

这里注意资源服务器应该是和授权服务器分开的,这里为了演示方便,我把他们放在一起了。这里对/api/下的所有请求进行拦截认证。

我们在pom.xml中引入了Security 的依赖,那么我们是需要使用到它的,那么我们创建一个WebSecurityConfig并且继承自WebSecurityConfigurerAdapter这个适配器类

  1. @EnableWebSecurity
  2. @Configuration
  3. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Autowired
  5. private CustomerUserService customerUserService;
  6. @Autowired
  7. public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
  8. authenticationManagerBuilder
  9. .userDetailsService(this.customerUserService);
  10. }
  11. }

这里使用了AuthenticationManagerBuilder来管理认证信息,最后我们创建一个UserController 来进行测试:

  1. @Controller
  2. public class UserController {
  3. @RequestMapping("/api/userinfo")
  4. public ResponseEntity<UserInfo> getUserInfo() {
  5. UserInfo user = (UserInfo) SecurityContextHolder.getContext()
  6. .getAuthentication().getPrincipal();
  7. String email = user.getUsername();
  8. user.setName(user.getUsername());
  9. user.setEmail(email);
  10. return ResponseEntity.ok(user);
  11. }
  12. }

下面是application.properties配置:

  1. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  2. spring.datasource.url=jdbc:mysql://localhost:3306/_oauth2
  3. spring.datasource.username=root
  4. spring.datasource.password=root
  5. #jpa
  6. spring.jpa.hibernate.ddl-auto=update
  7. spring.jpa.show-sql=true

下面是这个资源需要的sql,这里为什么需要创建sql呢,因为我们是走的jdbc模式,下面这个sql的结构可以从JdbcClientDetailsService 这个类从获取,如下:
在这里插入图片描述

  1. SET NAMES utf8;
  2. SET FOREIGN_KEY_CHECKS = 0;
  3. -- ----------------------------
  4. -- Table structure for `oauth_client_details`
  5. -- ----------------------------
  6. DROP TABLE IF EXISTS `oauth_client_details`;
  7. CREATE TABLE `oauth_client_details` (
  8. `client_id` varchar(48) NOT NULL,
  9. `resource_ids` varchar(256) DEFAULT NULL,
  10. `client_secret` varchar(256) DEFAULT NULL,
  11. `scope` varchar(256) DEFAULT NULL,
  12. `authorized_grant_types` varchar(256) DEFAULT NULL,
  13. `web_server_redirect_uri` varchar(256) DEFAULT NULL,
  14. `authorities` varchar(256) DEFAULT NULL,
  15. `access_token_validity` int(11) DEFAULT NULL,
  16. `refresh_token_validity` int(11) DEFAULT NULL,
  17. `additional_information` varchar(4096) DEFAULT NULL,
  18. `autoapprove` varchar(256) DEFAULT NULL,
  19. PRIMARY KEY (`client_id`)
  20. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  21. -- ----------------------------
  22. -- Records of `oauth_client_details`
  23. -- ----------------------------
  24. BEGIN;
  25. INSERT INTO `oauth_client_details` VALUES ('clientapp', null, '112233', 'read_userinfo', 'authorization_code', 'http://localhost:9001/callback', null, '3600', null, null, null);
  26. COMMIT;
  27. SET FOREIGN_KEY_CHECKS = 1;

然后我们使用chrome浏览器访问http://localhost:8080/oauth/authorize?client_id=clientapp&redirect_uri=http://localhost:9001/callback&response_type=code&scope=read_userinfo

然后出现了身份认证:
在这里插入图片描述
我们输入账号和密码点击登陆后:

在这里插入图片描述
这里提示我们授权。我们点击Approve,如果点击了Deny就是拒绝授权。

在这里插入图片描述
这里我们就拿到了授权码,然后我们使用postman之类的http来进行后面的测试:
在这里插入图片描述
在这里插入图片描述
这里我们要填入客户端id 和密码,这里是来自数据里面的。这里所有的表单填入的信息都来自数据库表中的数据。

然后我们点击发送:
在这里插入图片描述
这里就可以拿到token了。然后我们就可以用token 来换取我们的api服务了
在这里插入图片描述

在这里插入图片描述
这里就拿到了我们api提供的信息了。

总结

这里使用了授权码模式的oauth2的认证,总体来说很简单的。注意这里的实验是不能用在生产级别的,如果要用到生产级,那么还需要对代码进行多次的封装和配置。

发表评论

表情:
评论列表 (有 0 条评论,80人围观)

还没有评论,来说两句吧...

相关阅读