基于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。
1.pom
org.springframework.boot spring-boot-starter-security org.springframework.security.oauth spring-security-oauth2
2.UserDetail实现认证第一步
MyUserDetailsService.java
@Autowired privatePasswordEncoderpasswordEncoder; /** *根据进行登录 *@paramusername *@return *@throwsUsernameNotFoundException */ @Override publicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{ log.info("登录用户名:"+username); Stringpassword=passwordEncoder.encode("123456"); //User三个参数(用户名+密码+权限) //根据查找到的用户信息判断用户是否被冻结 log.info("数据库密码:"+password); returnnewUser(username,password,AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); }
3.获取token的控制器
@RestController publicclassOauthController{ @Autowired privateClientDetailsServiceclientDetailsService; @Autowired privateAuthorizationServerTokenServicesauthorizationServerTokenServices; @Autowired privateAuthenticationManagerauthenticationManager; @PostMapping("/oauth/getToken") publicObjectgetToken(@RequestParamStringusername,@RequestParamStringpassword,HttpServletRequestrequest)throwsIOException{ Mapmap=newHashMap<>(8); //进行验证 Stringheader=request.getHeader("Authorization"); if(header==null&&!header.startsWith("Basic")){ map.put("code",500); map.put("message","请求投中无client信息"); returnmap; } String[]tokens=this.extractAndDecodeHeader(header,request); asserttokens.length==2; //获取clientId和clientSecret StringclientId=tokens[0]; StringclientSecret=tokens[1]; //获取ClientDetails ClientDetailsclientDetails=clientDetailsService.loadClientByClientId(clientId); if(clientDetails==null){ map.put("code",500); map.put("message","clientId不存在"+clientId); returnmap; //判断方言是否一致 }elseif(!StringUtils.equals(clientDetails.getClientSecret(),clientSecret)){ map.put("code",500); map.put("message","clientSecret不匹配"+clientId); returnmap; } //使用username、密码进行登录 UsernamePasswordAuthenticationTokenauthentication=newUsernamePasswordAuthenticationToken(username,password); //调用指定的UserDetailsService,进行用户名密码验证 Authenticationauthenticate=authenticationManager.authenticate(authentication); HrUtils.setCurrentUser(authenticate); //放到session中 //密码授权模式,组建authentication TokenRequesttokenRequest=newTokenRequest(newHashMap<>(),clientId,clientDetails.getScope(),"password"); OAuth2RequestoAuth2Request=tokenRequest.createOAuth2Request(clientDetails); OAuth2AuthenticationoAuth2Authentication=newOAuth2Authentication(oAuth2Request,authentication); OAuth2AccessTokentoken=authorizationServerTokenServices.createAccessToken(oAuth2Authentication); map.put("code",200); map.put("token",token.getValue()); map.put("refreshToken",token.getRefreshToken()); returnmap; } /** *解码请求头 */ privateString[]extractAndDecodeHeader(Stringheader,HttpServletRequestrequest)throwsIOException{ byte[]base64Token=header.substring(6).getBytes("UTF-8"); byte[]decoded; try{ decoded=Base64.decode(base64Token); }catch(IllegalArgumentExceptionvar7){ thrownewBadCredentialsException("Failedtodecodebasicauthenticationtoken"); } Stringtoken=newString(decoded,"UTF-8"); intdelim=token.indexOf(":"); if(delim==-1){ thrownewBadCredentialsException("Invalidbasicauthenticationtoken"); }else{ returnnewString[]{token.substring(0,delim),token.substring(delim+1)}; } } }
4.核心配置
(1)、Security配置类说明登录方式、登录页面、哪个url需要认证、注入登录失败/成功过滤器
@Configuration publicclassBrowserSecurityConfigextendsWebSecurityConfigurerAdapter{ /** *注入自定义的登录成功处理类 */ @Autowired privateMyAuthenticationSuccessHandlermySuccessHandler; /** *注入自定义的登录失败处理类 */ @Autowired privateMyAuthenticationFailHandlermyFailHandler; @Autowired privateValidateCodeFiltervalidateCodeFilter; /** *重写PasswordEncoder接口中的方法,实例化加密策略 *@return返回BCrypt加密策略 */ @Bean publicPasswordEncoderpasswordEncoder(){ returnnewBCryptPasswordEncoder(); } @Override protectedvoidconfigure(HttpSecurityhttp)throwsException{ //在UsernamePasswordAuthenticationFilter过滤器前加一个过滤器来搞验证码 http.addFilterBefore(validateCodeFilter,UsernamePasswordAuthenticationFilter.class) //表单登录方式 .formLogin() .loginPage("/authentication/require") //登录需要经过的url请求 .loginProcessingUrl("/authentication/form") .passwordParameter("pwd") .usernameParameter("user") .successHandler(mySuccessHandler) .failureHandler(myFailHandler) .and() //请求授权 .authorizeRequests() //不需要权限认证的url .antMatchers("/oauth/*","/authentication/*","/code/image").permitAll() //任何请求 .anyRequest() //需要身份认证 .authenticated() .and() //关闭跨站请求防护 .csrf().disable(); //默认注销地址:/logout http.logout(). //注销之后跳转的页面 logoutSuccessUrl("/authentication/require"); } /** *认证管理 * *@return认证管理对象 *@throwsException认证异常信息 */ @Override @Bean publicAuthenticationManagerauthenticationManagerBean()throwsException{ returnsuper.authenticationManagerBean(); } }
(2)、认证服务器
@Configuration @EnableAuthorizationServer publicclassMyAuthorizationServerConfigextendsAuthorizationServerConfigurerAdapter{ @Autowired privateAuthenticationManagerauthenticationManager; @Autowired privateMyUserDetailsServiceuserDetailsService; @Override publicvoidconfigure(AuthorizationServerSecurityConfigurersecurity)throwsException{ super.configure(security); } /** *客户端配置(给谁发令牌) *@paramclients *@throwsException */ @Override publicvoidconfigure(ClientDetailsServiceConfigurerclients)throwsException{ clients.inMemory().withClient("internet_plus") .secret("internet_plus") //有效时间2小时 .accessTokenValiditySeconds(72000) //密码授权模式和刷新令牌 .authorizedGrantTypes("refresh_token","password") .scopes("all"); } @Override publicvoidconfigure(AuthorizationServerEndpointsConfigurerendpoints)throwsException{ endpoints .authenticationManager(authenticationManager) .userDetailsService(userDetailsService); } }
@EnableResourceServer这个注解就决定了这是个资源服务器。它决定了哪些资源需要什么样的权限。
5、测试
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。