洞察探索如何通过一套代码实现跨平台小程序开发与高效管理,助力企业数字化转型
686
2023-06-30
基于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
2. UserDetail实现认证第一步
MyUserDetailsService.java
@Autowired
private PasswordEncoder passwordEncoder;
/**
* 根据进行登录hlEgyb
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("登录用户名:"+username);
String password = passwordEncoder.encode("123456");
//User三个参数 (用户名+密码+权限)
//根据查找到的用户信息判断用户是否被冻结
log.info("数据库密码:"+password);
return new User(username,password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
3. 获取token的控制器
@RestController
public class OauthController {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private AuthorizationServerTohlEgybkenServices authorizationServerTokenServices;
@Autowired
private AuthenticationManager authenticationManager;
@PostMapping("/oauth/getToken")
public Object getToken(@RequestParam String username, @RequestParam String password, HttpServletRequest request) throws IOException {
Map
//进行验证
String header = request.getHeader("Authorization");
if (header == null && !header.startsWith("Basic")) {
map.put("code",500);
map.put("message","请求投中无client信息");
return map;
}
String[] tokens = this.extractAndDecodeHeader(header, request);
assert tokens.length == 2;
//获取clientId 和 clientSecret
String clientId = tokens[0];
String clientSecret = tokens[1];
//获取 ClientDetails
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
if (clientDetails == null){
map.put("code",500);
map.put("message","clientId 不存在"+clientId);
return map;
//判断 方言 是否一致
}else if (!StringUtils.equals(clientDetails.getClientSecret(),clientSecret)){
map.put("code",500);
map.put("message","clientSecret 不匹配"+clientId);
return map;
}
//使用username、密码进行登录
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, password);
//调用指定的UserDetailsService,进行用户名密码验证
Authentication authenticate = authenticationManager.authenticate(authentication);
HrUtils.setCurrentUser(authenticate);
//放到session中
//密码授权 模式, 组建 authentication
TokenRequest tokenRequest = new TokenRequest(new HashMap<>(),clientId,clientDetails.getScope(),"password");
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request,authentication);
OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
map.put("code",200);
map.put("token",token.getValue());
map.put("refreshToken",token.getRefreshToken());
return map;
}
/**
* 解码请求头
*/
private String[] extractAndDecodeHeader(String header, HttpServletRequest request) throws IOException {
byte[] base64Token = header.substring(6).getBytes("UTF-8");
byte[] decoded;
try {
decoded = Base64.decode(base64Token);
} catch (IllegalArgumentException var7) {
throw new BadCredentialsException("Failed to decode basic authentication token");
}
String token = new String(decoded, "UTF-8");
int delim = token.indexOf(":");
if (delim == -1) {
throw new BadCredentialsException("Invalid basic authentication token");
} else {
return new String[]{token.substring(0, delim), token.substring(delim + 1)};
}
}
}
4. 核心配置
(1)、Security 配置类 说明登录方式、登录页面、哪个url需要认证、注入登录失败/成功过滤器
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 注入 自定义的 登录成功处理类
*/
@Autowired
private MyAuthenticationSuccessHandler mySuccessHandler;
/**
* 注入 自定义的 登录失败处理类
*/
@Autowired
private MyAuthenticationFailHandler myFailHandler;
@Autowired
private ValidateCodeFilter validateCodeFilter;
/**
* 重写PasswordEncoder 接口中的方法,实例化加密策略
* @return 返回 BCrypt 加密策略
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSechlEgyburity http) throws Exception {
//在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 认证管理对象
* @throws Exception 认证异常信息
*/
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
(2)、认证服务器
@Configuration
@EnableAuthorizationServer
public class MyAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private MyUserDetailsService userDetailsService;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
super.configure(security);
}
/**
* 客户端配置(给谁发令牌)
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("internet_plus")
.secret("internet_plus")
//有效时间 2小时
.accessTokenValiditySeconds(72000)
//密码授权模式和刷新令牌
.authorizedGrantTypes("refresh_token","password")
.scopes( "all");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
@EnableResourceServer这个注解就决定了这是个资源服务器。它决定了哪些资源需要什么样的权限。
5、测试
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~