基于SpringBoot整合oauth2实现token认证

前端之家收集整理的这篇文章主要介绍了基于SpringBoot整合oauth2实现token认证前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

这篇文章主要介绍了基于SpringBoot整合oauth2实现token 认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

session和token的区别:

  • session是空间换时间,而token是时间换空间。session占用空间,但是可以管理过期时间,token管理部了过期时间,但是不占用空间.
  • sessionId失效问题和token内包含。
  • session基于cookie,app请求并没有cookie 。
  • token更加安全(每次请求都需要带上)

Oauth2 密码授权流程

在oauth2协议里,每一个应用都有自己的一个clientId和clientSecret(需要去认证方申请),所以一旦想通过认证,必须要有认证方下发的clientId和secret。

基于SpringBoot整合oauth2实现token认证

1. pom

  1. <!--security-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-security</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.security.oauth</groupId>
  8. <artifactId>spring-security-oauth2</artifactId>
  9. </dependency>

2. UserDetail实现认证第一步

MyUserDetailsService.java

  1. @Autowired
  2. private PasswordEncoder passwordEncoder;
  3.  
  4. /**
  5. * 根据进行登录
  6. * @param username
  7. * @return
  8. * @throws UsernameNotFoundException
  9. */
  10. @Override
  11. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  12. log.info("登录用户名:"+username);
  13. String password = passwordEncoder.encode("123456");
  14. //User三个参数 (用户名+密码+权限)
  15. //根据查找到的用户信息判断用户是否被冻结
  16. log.info("数据库密码:"+password);
  17. return new User(username,password,AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
  18. }

3. 获取token的控制器

  1. @RestController
  2. public class OauthController {
  3.  
  4. @Autowired
  5. private ClientDetailsService clientDetailsService;
  6. @Autowired
  7. private AuthorizationServerTokenServices authorizationServerTokenServices;
  8. @Autowired
  9. private AuthenticationManager authenticationManager;
  10.  
  11. @PostMapping("/oauth/getToken")
  12. public Object getToken(@RequestParam String username,@RequestParam String password,HttpServletRequest request) throws IOException {
  13. Map<String,Object>map = new HashMap<>(8);
  14. //进行验证
  15. String header = request.getHeader("Authorization");
  16. if (header == null && !header.startsWith("Basic")) {
  17. map.put("code",500);
  18. map.put("message","请求投中无client信息");
  19. return map;
  20. }
  21. String[] tokens = this.extractAndDecodeHeader(header,request);
  22. assert tokens.length == 2;
  23. //获取clientId 和 clientSecret
  24. String clientId = tokens[0];
  25. String clientSecret = tokens[1];
  26. //获取 ClientDetails
  27. ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
  28. if (clientDetails == null){
  29. map.put("code","clientId 不存在"+clientId);
  30. return map;
  31. //判断 方言 是否一致
  32. }else if (!StringUtils.equals(clientDetails.getClientSecret(),clientSecret)){
  33. map.put("code","clientSecret 不匹配"+clientId);
  34. return map;
  35. }
  36. //使用username、密码进行登录
  37. UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username,password);
  38. //调用指定的UserDetailsService,进行用户名密码验证
  39. Authentication authenticate = authenticationManager.authenticate(authentication);
  40. HrUtils.setCurrentUser(authenticate);
  41. //放到session中
  42. //密码授权 模式,组建 authentication
  43. TokenRequest tokenRequest = new TokenRequest(new HashMap<>(),clientId,clientDetails.getScope(),"password");
  44.  
  45. OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
  46. OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request,authentication);
  47.  
  48. OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
  49. map.put("code",200);
  50. map.put("token",token.getValue());
  51. map.put("refreshToken",token.getRefreshToken());
  52. return map;
  53. }
  54.  
  55. /**
  56. * 解码请求头
  57. */
  58. private String[] extractAndDecodeHeader(String header,HttpServletRequest request) throws IOException {
  59. byte[] base64Token = header.substring(6).getBytes("UTF-8");
  60.  
  61. byte[] decoded;
  62. try {
  63. decoded = Base64.decode(base64Token);
  64. } catch (IllegalArgumentException var7) {
  65. throw new BadCredentialsException("Failed to decode basic authentication token");
  66. }
  67.  
  68. String token = new String(decoded,"UTF-8");
  69. int delim = token.indexOf(":");
  70. if (delim == -1) {
  71. throw new BadCredentialsException("Invalid basic authentication token");
  72. } else {
  73. return new String[]{token.substring(0,delim),token.substring(delim + 1)};
  74. }
  75. }
  76. }

4. 核心配置

(1)、Security 配置类 说明登录方式、登录页面、哪个url需要认证、注入登录失败/成功过滤器

  1. @Configuration
  2. public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
  3.  
  4. /**
  5. * 注入 自定义登录成功处理类
  6. */
  7. @Autowired
  8. private MyAuthenticationSuccessHandler mySuccessHandler;
  9. /**
  10. * 注入 自定义登录失败处理类
  11. */
  12. @Autowired
  13. private MyAuthenticationFailHandler myFailHandler;
  14.  
  15. @Autowired
  16. private ValidateCodeFilter validateCodeFilter;
  17.  
  18. /**
  19. * 重写PasswordEncoder 接口中的方法,实例化加密策略
  20. * @return 返回 BCrypt 加密策略
  21. */
  22. @Bean
  23. public PasswordEncoder passwordEncoder(){
  24. return new BCryptPasswordEncoder();
  25. }
  26.  
  27. @Override
  28. protected void configure(HttpSecurity http) throws Exception {
  29. //在UsernamePasswordAuthenticationFilter 过滤器前 加一个过滤器 来搞验证码
  30. http.addFilterBefore(validateCodeFilter,UsernamePasswordAuthenticationFilter.class)
  31. //表单登录 方式
  32. .formLogin()
  33. .loginPage("/authentication/require")
  34. //登录需要经过的url请求
  35. .loginProcessingUrl("/authentication/form")
  36. .passwordParameter("pwd")
  37. .usernameParameter("user")
  38. .successHandler(mySuccessHandler)
  39. .failureHandler(myFailHandler)
  40. .and()
  41. //请求授权
  42. .authorizeRequests()
  43. //不需要权限认证的url
  44. .antMatchers("/oauth/*","/authentication/*","/code/image").permitAll()
  45. //任何请求
  46. .anyRequest()
  47. //需要身份认证
  48. .authenticated()
  49. .and()
  50. //关闭跨站请求防护
  51. .csrf().disable();
  52. //默认注销地址:/logout
  53. http.logout().
  54. //注销之后 跳转页面
  55. logoutSuccessUrl("/authentication/require");
  56. }
  57.  
  58. /**
  59. * 认证管理
  60. *
  61. * @return 认证管理对象
  62. * @throws Exception 认证异常信息
  63. */
  64. @Override
  65. @Bean
  66. public AuthenticationManager authenticationManagerBean() throws Exception {
  67. return super.authenticationManagerBean();
  68. }
  69. }

(2)、认证服务器

  1. @Configuration
  2. @EnableAuthorizationServer
  3. public class MyAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
  4. @Autowired
  5. private AuthenticationManager authenticationManager;
  6.  
  7. @Autowired
  8. private MyUserDetailsService userDetailsService;
  9.  
  10. @Override
  11. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
  12. super.configure(security);
  13. }
  14.  
  15. /**
  16. * 客户端配置(给谁发令牌)
  17. * @param clients
  18. * @throws Exception
  19. */
  20. @Override
  21. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  22. clients.inMemory().withClient("internet_plus")
  23. .secret("internet_plus")
  24. //有效时间 2小时
  25. .accessTokenValiditySeconds(72000)
  26. //密码授权模式和刷新令牌
  27. .authorizedGrantTypes("refresh_token","password")
  28. .scopes( "all");
  29. }
  30.  
  31. @Override
  32. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  33. endpoints
  34. .authenticationManager(authenticationManager)
  35. .userDetailsService(userDetailsService);
  36. }
  37. }

@EnableResourceServer这个注解就决定了这是个资源服务器。它决定了哪些资源需要什么样的权限。

5、测试

基于SpringBoot整合oauth2实现token认证

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

猜你在找的Springboot相关文章