基于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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。