spring-security【表单认证】、【jwt认证】、【社交登录】
2021/5/12 18:28:28
本文主要是介绍spring-security【表单认证】、【jwt认证】、【社交登录】,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
1.spring-security是spring官方推荐的【认证、授权】框架
2.本文介绍spring-security在【表单认证】、【jwt认证】、【社交登录】3种场景中的运用
3.RBAC权限模块的代码,将以伪代码形式给出
总体介绍
过滤器链
spring-security使用多个Filter来实现:认证、授权、记住我、成功(失败)跳转、跨域访问、防跨站攻击。。。一系列功能。
其中【UsernamePasswordAuthenticationFilter】与【BasicAuthenticationFilter】为核心过滤器(与业务绑定),分别管理【用户名/密码的认证】与【token认证】
认证、授权流程
第一步:认证
根据username查询系统中是否存在该用户
第二步:授权
认证成功后,获取该用户的权限,封装为UserDetail对象(上图对于理解spring security整套认证、授权流程至关重要)
PS:根据此图,调试代码,弄明白spring-security整个认证、授权流程,那么这套框架的核心就理解的差不多了
案例
表单认证
1.流程图
2.实现
核心配置
@Override protected void configure(HttpSecurity http) throws Exception { // 允许iframe嵌套,解决:frame because it set 'X-Frame-Options' to 'deny 问题 http.headers().frameOptions().disable(); // 放行所有option请求 http.authorizeRequests() .requestMatchers(CorsUtils::isPreFlightRequest) .permitAll(); http.csrf().disable() // 关闭跨站攻击保护,否则无法进行跨域访问 .cors() // 开启跨域支持 .and().formLogin() .loginPage("/login.html") // 登录页 .loginProcessingUrl("/user/login") // 登录Action提交url .defaultSuccessUrl("/success.html").permitAll() .failureUrl("/error.html") // .failureHandler(failureHandler) // 登录失败自定义处理器(会覆盖failureUrl()的设置) // .successHandler(successHandler) // 登录成功自定义处理器(会覆盖defaultSuccessUrl()的设置) .and().logout() // 退出登录 .logoutUrl("/logout") // 退出Action提交url .addLogoutHandler(definedLogoutHandler) // 退出处理逻辑编写 .and().exceptionHandling().accessDeniedPage("/unauth.html") // 无权限访问时跳转的html // 放开访问权限的url .and().authorizeRequests() .antMatchers("/", "/user/login", "/logout", "/user/logout").permitAll() .anyRequest().authenticated(); // .and().rememberMe() // 【记住我】功能设置 // .and().sessionManagement() // session管理:session有效期、session个数(可实现互踢) }View Code
配置的说明,注释已经说的很详细了,可自行阅读
说明:
a. 跨站攻击【.csrf().disable()】必须要关闭,否则跨域配置【.cors()】不起作用
b. 登录action的url【/user/login】与退出登录action的url【/logout】只需要配置路径即可,不需要自己实现,由spring-security框架自行实现
跨域配置
@Bean CorsFilter corsFilter() { CorsConfiguration configuration = new CorsConfiguration(); configuration.addAllowedOrigin(CorsConfiguration.ALL); configuration.addAllowedHeader(CorsConfiguration.ALL); configuration.addAllowedMethod(CorsConfiguration.ALL); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return new CorsFilter(source); }View Code
补充
FormLogin模式虽然依托于session,但是仍然可以实现微服务架构下的单点登录
实现步骤:
a. session需要保存在一个公共可访问区域(数据库 or redis)
b. session登录后,需要扩展session的作用域范围
例如:两个服务:www.baidu.com,map.baidu.com
当在www.baidu.com登录成功后,得到的session的作用域为www.baidu.com,此时我们需要修改session的作用域为:baidu.com。
这样,当我们在登录成功的状态下,再访问map.baidu.com时,由于session的作用域为baidu.com,所以session在map.baidu.com下仍然有效,所以登录状态为【已登录】
jwt认证
1.流程图
BasicLogin模式,采用的是http身份认证,属于最简单的认证、授权功能
2.实现
jwt的认证过程,有两步:【登录-生成token】、【验证token】需要将以上两个步骤,封装为Filter,添加到spring-security整个Filter链中
1.登录-生成token
a. 自定义Filter,用此Filter替换掉UsernamePasswordAuthenticationFilter,这样过滤器链的【用户名-密码认证】,用的就是我们自定义的业务逻辑
b. 继承UsernamePasswordAuthenticationFilter,重写【获取用户传递的信息方法(attemptAuthentication)】、【认证成功方法(successfulAuthentication)】、【认证失败方法(unsuccessfulAuthentication)】,实现自定义认证逻辑
核心代码
获取表单数据:spring-security的认证方法,需要将用户输入封装为:UsernamePasswordAuthenticationToken(用户名,密码,权限)
@Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { //获取表单提交数据 try { User user = new ObjectMapper().readValue(request.getInputStream(), User.class); return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword())); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(); } }View Code
认证成功
@Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) { //认证成功,得到认证成功之后用户信息 SecurityUser user = (SecurityUser) authResult.getPrincipal(); //根据用户名生成token String token = tokenManager.generateToken(user); //返回token ResponseUtil.out(response, token); }View Code
认证失败
@Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { ResponseUtil.out(response, "认证失败"); }View Code
2.验证token
a. 自定义Filter,用此Filter替换掉BasicAuthenticationFilter。由于jwt依托于http协议,BasicAuthenticationFilter就是针对http的Filter,所以选择替换掉BasicAUthenticationFilter
b. 继承BasicAuthenticationFilter,重写【过滤器方法(doFilterInternal)】实现自定义业务逻辑
核心代码
认证过滤
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { //获取当前认证成功用户权限信息 UsernamePasswordAuthenticationToken authRequest = getAuthentication(request); //判断如果有权限信息,放到权限上下文中 if (authRequest != null) { SecurityContextHolder.getContext().setAuthentication(authRequest); } chain.doFilter(request, response); }View Code
获取用户认证信息
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) { //从header获取token String token = request.getHeader("token"); if (token != null) { // 用户名 String username = tokenManager.getUsernameFromToken(token); if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = userDetailsService.loadUserByUsername(username); if (tokenManager.validateToken(token, userDetails)) { //给使用该JWT令牌的用户进行授权 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, token, userDetails.getAuthorities()); return authenticationToken; } } } return null; }View Code
社交登录
1.流程图
a. 引导【client】跳转至【第三方应用-登录】进行【登录-授权】操作,成功后返回【code】
b. 【client】获取到【code】向【第三方应用-认证】换取【access_token】
c. 【client】获取到【access_token】向【第三方应用-资源】发起API请求,获取开放的【用户信息】
2.实现思路
a. 【登录功能】由【第三方平台】实现,登录成功后,需要将返回的信息保存入本地。与【本地用户】建立关联关系
b. 【认证功能】与jwt认证功能类似,只需要做微调
3.实现(本实例使用【新浪微博开放平台】)
1.第三方平台access_token信息
【uid】用户标志id,需要用它与本地用户建立关联关系
【expire_in】access_token有效日期,生成jwt时有效期需要使用该属性
这篇关于spring-security【表单认证】、【jwt认证】、【社交登录】的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-28AI给的和自己写的Python代码,都无法改变输入框的内容,替换也不行
- 2024-09-27Sentinel配置限流资料:新手入门教程
- 2024-09-27Sentinel配置限流资料详解
- 2024-09-27Sentinel限流资料:新手入门教程
- 2024-09-26Sentinel限流资料入门详解
- 2024-09-26Springboot框架资料:初学者入门教程
- 2024-09-26Springboot框架资料详解:新手入门教程
- 2024-09-26Springboot企业级开发资料:新手入门指南
- 2024-09-26SpringBoot企业级开发资料新手指南
- 2024-09-26Springboot微服务资料入门教程