分布式整合之重写认证的过滤器|学习笔记

简介: 快速学习分布式整合之重写认证的过滤器

开发者学堂课程【Spring Security知识精讲与实战演示(三)分布式整合之重写认证的过滤器】学习笔记与课程紧密联系,让用户快速学习知识

课程地址https://developer.aliyun.com/learning/course/732/detail/13071


分布式整合之重写认证的过滤器

分布式整合之重写认证的过滤器

之前编写了RoleMapper和UserMapper,但是忘记在

AuthServerApplication.java 代码中加上 @MapperScan("com itheima. mapper"),这样之后就可以自动扫描并生成代理对象。

import com itheima.config.RsaKeyProperties;

import org.mybatis.spr ing. annotation. MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.

SpringBootApplication;

Import org.springframework.boot.context.proper

ties.EnableConfigurationProperties;

@SpringBootApplication

@MapperScan("com itheima. mapper")

@EnableConfigurationProperties(RsaKeyProperties.class)

public class AuthServerApplication {

public static void main(String[] args){

SpringApplication.run(AuthServerApplication.class, args);

}

}

另外,在RsaKeyProperties.java中不需要

@ConfigurationProperties("rsa.key")加入@Configuratio,因为声明了配置类就意味着当前对象不放入aoc容器中,而我们需要将当前对象放入容器中,故不需要这个注解。

import javax. annotation. PostConstruct;

import java. security. PrivateKey;

import java. security. PublicKey;

@ConfigurationProperties("rsa.key") .

public class RsaKeyProperties {

private Str ing pubKeyFile;

private String pr KeyFile;

private PublicKey publicKey;

private PrivateKey privateKey;

接下来,重新定义认证方法:

创建一个新的过滤器,名称为 filter.JwtTokenFilter 或者 filter.JwtLoginFilter,如下图。

image.png

package com. itheima.filter ;

public class JwtLoginFilter{

}

JwtLoginFilter 里,需要对默认的 UsernamePasswordluthenticationFilter 进行继承,继承的目的是为了重写其中的两个方法。

package com. itheima.filter ;

import org.springframework. security.web. authentic

ation. UsernamePasswordluthenticationFilter;

public class JwtLoginFilter extends UsernamePassword

AuthenticationFilter{

}

第一是认证逻辑,内容如下

public Authentication attemptAuthentication(HttpS

ervletRequest request,HttpServletResponse response) throws

if (this.postOnly && !request.getMethod().equals("PO

ST")) {

throw new AuthenticationServiceException("Authentic

ation method not supported: " + request.getMethod

} else {

String username = this.obtainUsername (request);

String password = this.obtainPassword(reqhest);

if (username == null){

username = “”;

}

if (password == null) {

password = "";

}

username = username.trim() ;

UsernamePassworduthenticationToken authRequest = new UsernamePasswordAuthenticationToken(usern

amethis.setDetails(request,authRequest);

return this.getAuthenticationManager (). Authenticate

(authRequest);

}

}

将上述内容粘贴进JwtLoginFilte,只需要留return一句:

Import org.springframework.security.core.Authentic

ationException;

import org.springframework.security.web. authen

tication. UsernamePassworduthenticationFilter;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse ;

public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

public Authentication attempt;huthentication(HttpS

ervletRequest request,HttpServrletResponse response) throws Authentican

return this.getAuthenticationManager(). Authenticate

(authRequest);

}

}

authRequestUsernamePassvordauthenticationI

Token authRequest = new UsernamePassword

Quthentication Token(usernamepassword)

之后将这个token粘进JwtLoginFilte

public Authentication attempt;huthentication(HttpS

ervletRequest request,HttpServrletResponse response) throws Authentican

UsernamePassvordauthenticationIToken authRequest = new UsernamePasswordquthentication

Token(username,password)

return this.getAuthenticationManager(). Authenticate

(authRequest);

}

}

这个token里需要传入 username和password,在这里可以直接从请求体中解析出来;getAuthenticationManager()对象是要 AuthenticationManager

public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

private AuthenticationManager authenticationManager;

注:以上代码是没有值的,需要生成一个带参数的构造方法。

private RsaKeyProperties prop;

public JwtLoginFilter(AuthenticationManager authenticationManager,RsaKeyProperties prop){

this.authenticationManager = authenticationManager ;

this.prop = prop;

}

public Authentication attempt;huthentication(HttpS

ervletRequest request,HttpServrletResponse response) throws AuthenticanException {

注:获取username和password,这里是有异常的,要进行try/catch Block操作。

Try{

SysUser sysUser = new ObjectMapper().readValue(request.getInputStream(),SysUser.class);

UsernamePassvordauthenticationIToken authRequest = new UsernamePasswordquthenticationToken(sysUser.getUsername(), sysUser.getPassword())

return this.getAuthenticationManager(). Authenticate

(authRequest);

}catch (Exception e) {

throw new RuntimeException(e);

}

}

得到用户对象之后,username和password改为sysUser.getUsername(), sysUser.getPassword(),且这两个数据都是用户输入过来的

接下来可以输入throw new RuntimeException(e)将异常抛出去

注意,在这个代码中是异步请求并未跳转任何界面,如果没有成功,要提示用户,直接抛异常用户是看不见的,可以进行以下操作提示用户。

return this.getAuthenticationManager(). Authenticate

(authRequest);

}catch (Exception e) {

try {

//登陆成功时,返回JSON格式进行提示

response.setContentType("application/json; charset=

utf-8"");

response. setStatus (HttpServletResponse.SC_UNAUT

HORIZED);

PrintWriter out = response.getWriter() ;

Map resultMap = new HashMap();

resultMap.put("code",HttpServletResponse.SC_UNAU

THORIZED);

resultMap. put("msg","用户名或密码错误!")

out.write(new 0bjectMapper ().writeValueAsString (resultMapp )

out.flush() ;

out.close();

throw new RuntimeException(e);

} catch (Exception outEx)【

outEx.printStackTrace() ;

}

throw new RuntimeException(e);

}

}

到此,上面的认证逻辑完成,其会根据后续的认证操作进行判断,用户名或密码正确则认证通过,认证失败则显示“用户名或密码错误”;如果认证成功,会继续执行一段代码,这段代码写在

UsernamePasswordAuthenticationFilter过滤器的副类中:

Protected voids uccessfulkuthentication(HttpServlet

Request request,HittpServletResponse response,FilterChain chain, Authentican Exception();

if (this. logger.isDebugEnabled()){

this. logger. debug (o:"Authentication success.Upda

ting SecurityContextHolder to contain:" + authResult);

}SecurityContextHolder.getContext(.setAuthentication(authResult);

this.rememberMeServices.loginSuccess(request,response,authResult);

if (this.eventPublisher != null){

this.eventPublisher. publishEvent(new Interactive

AuthenticationSuccessEvent(authResult,this.getClass()>);

this. successHandler. onAuthenticationSuccess(request,response,authResult);

}

将上述内容中

Protected voids uccessfulkuthentication(HttpServlet

Request request,HittpServletResponse response,FilterChain chain, Authentication authResult)throws I0Exception,ServletException

的粘进JwtLoginFilte,之后这下面要生成token:

Protected voids uccessfulkuthentication(HttpServlet

Request request,HittpServletResponse response,FilterChain chain, Authentican Exception();

String token = JwtUtils.generateTokenExpire InMinutes(userT prop.getPrivateKey(),expire:24* 60) ;

}

}

注:generateTokenExpire InMinutes 里的Object usqr Info,代表自己定义的用户对象;PrivateKey privateKey,代表加密需要使用的私钥;int expire),代表过期时间

现在这里的user对象是不存在的,下面创建user对象:

Protected voids uccessfulkuthentication(HttpServlet

Request request,HittpServletResponse response,FilterChain chain, Authentican Exception();

SysUser user = new SysUser();

user.setUsername(authResult.getName()) ;

user.setRoles((List<SysRole>) authResult.getAuthorities();

String token = JwtUtils.generateTokenExpire InMinutes(userT prop.getPrivateKey(),expire:24* 60) ;

}

}

至此,token完成,需要将token写回给请求者,可以将其写回到请求头里面,里面的名称可以随便取,但一般都为"Authorization","Bearer" + token

String token = JwtUtils.generateTokenExpire InMinutes(userT prop.getPrivateKey(),expire:24* 60) ;

res.addHeader("Authorization","Bearer" + token);

try {

//登陆成功时,返回JSON格式进行提示

response.setContentType("application/json; charset=

utf-8"");

response. setStatus (HttpServletResponse.SC_OK);

PrintWriter out = response.getWriter() ;

Map resultMap = new HashMap();

resultMap.put("code",HttpServletResponse.SC_OK);

resultMap. put("msg","证通过!");

out.write(new 0bjectMapper ().writeValueAsString (resultMapp )

out.flush() ;

out.close();

throw new RuntimeException(e);

} catch (Exception outEx)【

outEx.printStackTrace() ;

}

}

认证成功之后回写 token 操作完成。

相关文章
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
1542 0
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
772 1
|
SpringCloudAlibaba Java 测试技术
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(六)Hystrix(豪猪哥)的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(六)Hystrix(豪猪哥)的使用
395 1
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(三)Eureka服务注册中心
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(三)Eureka服务注册中心
379 1
|
消息中间件 SpringCloudAlibaba Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
1707 0
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(五)OpenFeign的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(五)OpenFeign的使用
594 0
|
负载均衡 算法 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(四)Ribbon的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(四)Ribbon的使用
458 0
|
6月前
|
存储 负载均衡 NoSQL
【赵渝强老师】Redis Cluster分布式集群
Redis Cluster是Redis的分布式存储解决方案,通过哈希槽(slot)实现数据分片,支持水平扩展,具备高可用性和负载均衡能力,适用于大规模数据场景。
456 2
|
6月前
|
存储 缓存 NoSQL
【📕分布式锁通关指南 12】源码剖析redisson如何利用Redis数据结构实现Semaphore和CountDownLatch
本文解析 Redisson 如何通过 Redis 实现分布式信号量(RSemaphore)与倒数闩(RCountDownLatch),利用 Lua 脚本与原子操作保障分布式环境下的同步控制,帮助开发者更好地理解其原理与应用。
407 6
|
7月前
|
存储 缓存 NoSQL
Redis核心数据结构与分布式锁实现详解
Redis 是高性能键值数据库,支持多种数据结构,如字符串、列表、集合、哈希、有序集合等,广泛用于缓存、消息队列和实时数据处理。本文详解其核心数据结构及分布式锁实现,帮助开发者提升系统性能与并发控制能力。

热门文章

最新文章