当前位置:   article > 正文

Spring Security OAuth2_spring-security-oauth2-autoconfigure

spring-security-oauth2-autoconfigure

依赖

  1. <dependency>
  2. <groupId>io.jsonwebtoken</groupId>
  3. <artifactId>jjwt</artifactId>
  4. <version>0.9.0</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.security</groupId>
  8. <artifactId>spring-security-data</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.springframework.cloud</groupId>
  12. <artifactId>spring-cloud-starter-oauth2</artifactId>
  13. <exclusions>
  14. <exclusion>
  15. <groupId>org.springframework.security.oauth.boot</groupId>
  16. <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  17. </exclusion>
  18. </exclusions>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.security.oauth.boot</groupId>
  22. <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  23. <version>2.1.3.RELEASE</version>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.cloud</groupId>
  27. <artifactId>spring-cloud-starter-security</artifactId>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-actuator</artifactId>
  32. </dependency>
  33. <dependency>
  34. <groupId>com.alibaba</groupId>
  35. <artifactId>fastjson</artifactId>
  36. <version>1.2.31</version>
  37. </dependency>

config包

AuthorizationServerConfig类

  1. package com.zb.oauth.cofig;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.security.authentication.AuthenticationManager;
  7. import org.springframework.security.core.userdetails.UserDetailsService;
  8. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  9. import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
  10. import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
  11. import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
  12. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
  13. import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
  14. import org.springframework.security.oauth2.provider.ClientDetailsService;
  15. import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
  16. import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
  17. import org.springframework.security.oauth2.provider.token.TokenStore;
  18. import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
  19. import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
  20. import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
  21. import javax.annotation.Resource;
  22. import javax.sql.DataSource;
  23. import java.security.KeyPair;
  24. @Configuration
  25. @EnableAuthorizationServer
  26. class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
  27. //SpringSecurity 用户自定义授权认证类
  28. @Autowired
  29. UserDetailsService userDetailsService;
  30. //授权认证管理器
  31. @Autowired
  32. AuthenticationManager authenticationManager;
  33. //令牌持久化存储接口
  34. @Autowired
  35. TokenStore tokenStore;
  36. //数据源,用于从数据库获取数据进行认证操作,测试可以从内存中获取
  37. @Autowired
  38. private DataSource dataSource;
  39. //jwt令牌转换器
  40. @Autowired
  41. private JwtAccessTokenConverter jwtAccessTokenConverter;
  42. @Autowired
  43. private CustomUserAuthenticationConverter customUserAuthenticationConverter;
  44. @Resource(name = "keyProp")
  45. private KeyProperties keyProperties;
  46. /***
  47. * 客户端信息配置
  48. * @param clients
  49. * @throws Exception
  50. */
  51. @Override
  52. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  53. clients.jdbc(dataSource).clients(this.clientDetails());
  54. // clients.inMemory()
  55. // .withClient("changgou") //客户端id
  56. // .secret("changgou") //秘钥
  57. // .redirectUris("http://localhost") //重定向地址
  58. // .accessTokenValiditySeconds(3600) //访问令牌有效期
  59. // .refreshTokenValiditySeconds(3600) //刷新令牌有效期
  60. // .authorizedGrantTypes(
  61. // "authorization_code", //根据授权码生成令牌
  62. // "client_credentials", //客户端认证
  63. // "refresh_token", //刷新令牌
  64. // "password") //密码方式认证
  65. // .scopes("app"); //客户端范围,名称自定义,必填
  66. }
  67. /***
  68. * 授权服务器端点配置
  69. * @param endpoints
  70. * @throws Exception
  71. */
  72. @Override
  73. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  74. endpoints.accessTokenConverter(jwtAccessTokenConverter)
  75. .authenticationManager(authenticationManager)//认证管理器
  76. .tokenStore(tokenStore) //令牌存储
  77. .userDetailsService(userDetailsService); //用户信息service
  78. }
  79. /***
  80. * 授权服务器的安全配置
  81. * @param oauthServer
  82. * @throws Exception
  83. */
  84. @Override
  85. public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
  86. oauthServer.allowFormAuthenticationForClients()
  87. .passwordEncoder(new BCryptPasswordEncoder())
  88. .tokenKeyAccess("permitAll()")
  89. .checkTokenAccess("isAuthenticated()");
  90. }
  91. //读取密钥的配置
  92. @Bean("keyProp")
  93. public KeyProperties keyProperties() {
  94. return new KeyProperties();
  95. }
  96. //客户端配置
  97. @Bean
  98. public ClientDetailsService clientDetails() {
  99. return new JdbcClientDetailsService(dataSource);
  100. }
  101. @Bean
  102. @Autowired
  103. public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
  104. return new JwtTokenStore(jwtAccessTokenConverter);
  105. }
  106. /****
  107. * JWT令牌转换器
  108. * @param customUserAuthenticationConverter
  109. * @return
  110. */
  111. @Bean
  112. public JwtAccessTokenConverter jwtAccessTokenConverter(CustomUserAuthenticationConverter customUserAuthenticationConverter) {
  113. JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
  114. KeyPair keyPair = new KeyStoreKeyFactory(
  115. keyProperties.getKeyStore().getLocation(), //证书路径 changgou.jks
  116. keyProperties.getKeyStore().getSecret().toCharArray()) //证书秘钥 changgouapp
  117. .getKeyPair(
  118. keyProperties.getKeyStore().getAlias(), //证书别名 changgou
  119. keyProperties.getKeyStore().getPassword().toCharArray()); //证书密码 changgou
  120. converter.setKeyPair(keyPair);
  121. //配置自定义的CustomUserAuthenticationConverter
  122. DefaultAccessTokenConverter accessTokenConverter = (DefaultAccessTokenConverter) converter.getAccessTokenConverter();
  123. accessTokenConverter.setUserTokenConverter(customUserAuthenticationConverter);
  124. return converter;
  125. }
  126. }

CustomUserAuthenticationConverter类

  1. package com.zb.oauth.cofig;
  2. import com.zb.oauth.util.UserJwt;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.security.core.Authentication;
  5. import org.springframework.security.core.authority.AuthorityUtils;
  6. import org.springframework.security.core.userdetails.UserDetails;
  7. import org.springframework.security.core.userdetails.UserDetailsService;
  8. import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
  9. import org.springframework.stereotype.Component;
  10. import java.util.LinkedHashMap;
  11. import java.util.Map;
  12. @Component
  13. public class CustomUserAuthenticationConverter extends DefaultUserAuthenticationConverter {
  14. @Autowired
  15. UserDetailsService userDetailsService;
  16. @Override
  17. public Map<String, ?> convertUserAuthentication(Authentication authentication) {
  18. LinkedHashMap response = new LinkedHashMap();
  19. String name = authentication.getName();
  20. response.put("username", name);
  21. Object principal = authentication.getPrincipal();
  22. UserJwt userJwt = null;
  23. if (principal instanceof UserJwt) {
  24. userJwt = (UserJwt) principal;
  25. } else {
  26. //refresh_token默认不去调用userdetailService获取用户信息,这里我们手动去调用,得到 UserJwt
  27. UserDetails userDetails = userDetailsService.loadUserByUsername(name);
  28. userJwt = (UserJwt) userDetails;
  29. }
  30. response.put("name", userJwt.getName());
  31. response.put("id", userJwt.getId());
  32. //公司 response.put("compy", "songsi");
  33. if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
  34. response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
  35. }
  36. return response;
  37. }
  38. }

UserDetailsServiceImpl类

需要用户微服务的接口进行远程调用

  1. package com.zb.oauth.cofig;
  2. import com.zb.client.UserModelFeignClient;
  3. import com.zb.oauth.util.UserJwt;
  4. import com.zb.dto.UserModelDto;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.security.core.Authentication;
  7. import org.springframework.security.core.authority.AuthorityUtils;
  8. import org.springframework.security.core.context.SecurityContextHolder;
  9. import org.springframework.security.core.userdetails.User;
  10. import org.springframework.security.core.userdetails.UserDetails;
  11. import org.springframework.security.core.userdetails.UserDetailsService;
  12. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  13. import org.springframework.security.oauth2.provider.ClientDetails;
  14. import org.springframework.security.oauth2.provider.ClientDetailsService;
  15. import org.springframework.stereotype.Service;
  16. import org.springframework.util.ObjectUtils;
  17. import org.springframework.util.StringUtils;
  18. /*****
  19. * 自定义授权认证类
  20. */
  21. @Service
  22. public class UserDetailsServiceImpl implements UserDetailsService {
  23. @Autowired
  24. ClientDetailsService clientDetailsService;
  25. @Autowired
  26. private UserModelFeignClient userModelFeignClient;
  27. /****
  28. * 自定义授权认证
  29. * @param username
  30. * @return
  31. * @throws UsernameNotFoundException
  32. */
  33. @Override
  34. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  35. //取出身份,如果身份为空说明没有认证
  36. Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  37. //没有认证统一采用httpbasic认证,httpbasic中存储了client_id和client_secret,开始认证client_id和client_secret
  38. if (authentication == null) {
  39. ClientDetails clientDetails = clientDetailsService.loadClientByClientId(username);
  40. if (clientDetails != null) {
  41. //秘钥
  42. String clientSecret = clientDetails.getClientSecret();
  43. //静态方式
  44. // return new User(username,new BCryptPasswordEncoder().encode(clientSecret), AuthorityUtils.commaSeparatedStringToAuthorityList(""));
  45. //数据库查找方式
  46. return new User(username, clientSecret, AuthorityUtils.commaSeparatedStringToAuthorityList(""));
  47. }
  48. }
  49. if (StringUtils.isEmpty(username)) {
  50. return null;
  51. }
  52. //feign远程调用用户微服务的登录放法,获取用户dto对象
  53. UserModelDto info = userModelFeignClient.info(username);
  54. if (ObjectUtils.isEmpty(info)) {
  55. return null;
  56. }
  57. //根据用户名查询用户信息
  58. String pwd = info.getPassword();
  59. //创建User对象
  60. //用户权力
  61. String permissions = "";
  62. UserJwt userDetails = new UserJwt(username, pwd, AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));
  63. return userDetails;
  64. }
  65. }

WebSecurityConfig类

configure()方法给登录退出接口放行

  1. package com.zb.oauth.cofig;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.core.annotation.Order;
  5. import org.springframework.security.authentication.AuthenticationManager;
  6. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  7. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  8. import org.springframework.security.config.annotation.web.builders.WebSecurity;
  9. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  10. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  11. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  12. import org.springframework.security.crypto.password.PasswordEncoder;
  13. @Configuration
  14. @EnableWebSecurity
  15. @Order(-1)
  16. class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  17. /***
  18. * 忽略安全拦截的URL
  19. * @param web
  20. * @throws Exception
  21. */
  22. @Override
  23. public void configure(WebSecurity web) throws Exception {
  24. web.ignoring().antMatchers(
  25. "/my-auth/login/**",
  26. "/user/logout");
  27. }
  28. /***
  29. * 创建授权管理认证对象
  30. * @return
  31. * @throws Exception
  32. */
  33. @Bean
  34. @Override
  35. public AuthenticationManager authenticationManagerBean() throws Exception {
  36. AuthenticationManager manager = super.authenticationManagerBean();
  37. return manager;
  38. }
  39. @Override
  40. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  41. super.configure(auth);
  42. }
  43. /***
  44. * 采用BCryptPasswordEncoder对密码进行编码
  45. * @return
  46. */
  47. @Bean
  48. public PasswordEncoder passwordEncoder() {
  49. return new BCryptPasswordEncoder();
  50. }
  51. /****
  52. *
  53. * @param http
  54. * @throws Exception
  55. */
  56. @Override
  57. public void configure(HttpSecurity http) throws Exception {
  58. http.csrf().disable()
  59. .httpBasic() //启用Http基本身份验证
  60. .and()
  61. .formLogin() //启用表单身份验证
  62. .and()
  63. .authorizeRequests() //限制基于Request请求访问
  64. .anyRequest()
  65. .authenticated(); //其他请求都需要经过验证
  66. }
  67. }

util包

AuthToken类

  1. package com.zb.oauth.util;
  2. import java.io.Serializable;
  3. public class AuthToken implements Serializable {
  4. //令牌信息
  5. String accessToken;
  6. //刷新token(refresh_token)
  7. String refreshToken;
  8. //jwt短令牌
  9. String jti;
  10. public String getAccessToken() {
  11. return accessToken;
  12. }
  13. public void setAccessToken(String accessToken) {
  14. this.accessToken = accessToken;
  15. }
  16. public String getRefreshToken() {
  17. return refreshToken;
  18. }
  19. public void setRefreshToken(String refreshToken) {
  20. this.refreshToken = refreshToken;
  21. }
  22. public String getJti() {
  23. return jti;
  24. }
  25. public void setJti(String jti) {
  26. this.jti = jti;
  27. }
  28. }

UserJwt类

  1. package com.zb.oauth.util;
  2. import org.springframework.security.core.GrantedAuthority;
  3. import org.springframework.security.core.userdetails.User;
  4. import java.util.Collection;
  5. public class UserJwt extends User {
  6. private String id; //用户ID
  7. private String name; //用户名字
  8. private String comny;//设置公司
  9. public UserJwt(String username, String password, Collection<? extends GrantedAuthority> authorities) {
  10. super(username, password, authorities);
  11. }
  12. public String getId() {
  13. return id;
  14. }
  15. public void setId(String id) {
  16. this.id = id;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. }

service.impl包

AutoServiceImpl类

  1. package com.zb.oauth.service.impl;
  2. import com.zb.oauth.service.AuthService;
  3. import com.zb.oauth.util.AuthToken;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.cloud.client.ServiceInstance;
  6. import org.springframework.cloud.client.discovery.DiscoveryClient;
  7. import org.springframework.http.HttpEntity;
  8. import org.springframework.http.HttpMethod;
  9. import org.springframework.http.ResponseEntity;
  10. import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
  11. import org.springframework.stereotype.Service;
  12. import org.springframework.util.Base64Utils;
  13. import org.springframework.util.LinkedMultiValueMap;
  14. import org.springframework.web.client.RestTemplate;
  15. import java.sql.ClientInfoStatus;
  16. import java.util.List;
  17. import java.util.Map;
  18. @Service
  19. public class AutoServiceImpl implements AuthService {
  20. @Autowired
  21. private RestTemplate restTemplate;
  22. @Autowired
  23. private DiscoveryClient discoveryClient;
  24. @Override
  25. public AuthToken login(String username, String passwd, String clientId, String clientSecret) {
  26. //根据微服务name获取接口类型list集合
  27. List<ServiceInstance> instances = discoveryClient.getInstances("user-auth");
  28. //取第一个接口获取ip和端口号生成url地址
  29. ServiceInstance serviceInstance = instances.get(0);
  30. String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/oauth/token";
  31. System.out.println(url);
  32. //创建一个LinkedMultiValueMap的body
  33. LinkedMultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
  34. //给body添加需要的参数
  35. body.add("grant_type", "password");
  36. body.add("username", username);
  37. body.add("password", passwd);
  38. //创建一个LinkedMultiValueMap的header
  39. LinkedMultiValueMap<String, String> header = new LinkedMultiValueMap<String, String>();
  40. //给请求头添加参数
  41. //调用本类的myEncoder方法编译
  42. header.add("Authorization", myEncoder(clientId, clientSecret));
  43. try {
  44. //用restTemplate.exchange()发起请求,
  45. //方法参数:地址,请求方式,HttpEntity<>(请求体,请求头),返回数据的类型
  46. //创建一个ResponseEntity<返回数据的类型>的response对象接收POST请求返回的数据
  47. ResponseEntity<Map> response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, header), Map.class);
  48. //调用getBody()获取response对象中返回的map
  49. Map map = response.getBody();
  50. System.out.println(map);
  51. //创建AuthToken对象并初始化
  52. AuthToken authToken = new AuthToken();
  53. authToken.setAccessToken(map.get("access_token").toString());
  54. authToken.setJti(map.get("jti").toString());
  55. authToken.setRefreshToken(map.get("refresh_token").toString());
  56. return authToken;
  57. } catch (Exception e) {
  58. e.printStackTrace();
  59. }
  60. return null;
  61. }
  62. //clientId,clientId在application.yml配置文件中赋值
  63. //在controller层使用@Value("${auth.clientId}"),@Value("${auth.clientSecret}")获取
  64. private String myEncoder(String clientId, String clientSecret) {
  65. String str = clientId + ":" + clientSecret;
  66. byte[] encode = Base64Utils.encode(str.getBytes());
  67. return "Basic " + new String(encode);
  68. }
  69. }

controller层

  1. package com.zb.oauth.controller;
  2. import com.zb.oauth.service.AuthService;
  3. import com.zb.oauth.util.AuthToken;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.beans.factory.annotation.Value;
  6. import org.springframework.web.bind.annotation.PostMapping;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RequestParam;
  9. import org.springframework.web.bind.annotation.RestController;
  10. @RestController
  11. @RequestMapping("my-auth")
  12. public class AuthController {
  13. @Value("${auth.clientId}")
  14. private String clientId;
  15. @Value("${auth.clientSecret}")
  16. private String clientSecret;
  17. @Autowired
  18. private AuthService authService;
  19. @PostMapping("login")
  20. public AuthToken login(@RequestParam("username") String username, @RequestParam("passwd") String passwd) {
  21. return authService.login(username, passwd, clientId, clientSecret);
  22. }
  23. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/83416
推荐阅读
相关标签
  

闽ICP备14008679号