温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

springboot怎么以FTP方式上传文件到远程服务器

发布时间:2021-11-20 10:54:14 来源:亿速云 阅读:136 作者:柒染 栏目:编程语言

今天就跟大家聊聊有关springboot怎么以FTP方式上传文件到远程服务器,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

通过笔者前两篇文章的说明,相信大家已经知道JWT是什么,怎么用,该如何结合Spring Security使用。那么本节就用代码来具体的实现一下JWT登录认证及鉴权的流程。

一、环境准备工作

建立Spring Boot项目并集成了Spring Security,项目可以正常启动

通过controller写一个HTTP的GET方法服务接口,比如:“/hello”

实现最基本的动态数据验证及权限分配,即实现UserDetailsService接口和UserDetails接口。这两个接口都是向Spring Security提供用户、角色、权限等校验信息的接口

如果你学习过Spring Security的formLogin登录模式,请将HttpSecurity配置中的formLogin()配置段全部去掉。因为JWT完全使用JSON接口,没有from表单提交。

HttpSecurity配置中一定要加上csrf().disable(),即暂时关掉跨站攻击CSRF的防御。这样是不安全的,我们后续章节再做处理。

以上的内容,我们在之前的文章中都已经讲过。如果仍然不熟悉,可以翻看本号之前的文章。

## 二、开发JWT工具类

通过maven坐标引入JWT工具包jjwt

<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version></dependency>

在application.yml中加入如下自定义一些关于JWT的配置

jwt:  header: JWTHeaderName secret: aabbccdd  expiration: 3600000

其中header是携带JWT令牌的HTTP的Header的名称。虽然我这里叫做JWTHeaderName,但是在实际生产中可读性越差越安全。

secret是用来为JWT基础信息加密和解密的密钥。虽然我在这里在配置文件写死了,但是在实际生产中通常不直接写在配置文件里面。而是通过应用的启动参数传递,并且需要定期修改。

expiration是JWT令牌的有效时间。

写一个Spring Boot配置自动加载的工具类。

@Data@ConfigurationProperties(prefix = "jwt") //配置自动加载,prefix是配置的前缀@Componentpublic class JwtTokenUtil implements Serializable { private String secret; private Long expiration; private String header; /**  * 生成token令牌  *  * @param userDetails 用户  * @return 令token牌  */ public String generateToken(UserDetails userDetails) {  Map<String, Object> claims = new HashMap<>(2);  claims.put("sub", userDetails.getUsername());  claims.put("created", new Date());  return generateToken(claims); } /**  * 从令牌中获取用户名  *  * @param token 令牌  * @return 用户名  */ public String getUsernameFromToken(String token) {  String username;  try {   Claims claims = getClaimsFromToken(token);   username = claims.getSubject();  } catch (Exception e) {   username = null;  }  return username; } /**  * 判断令牌是否过期  *  * @param token 令牌  * @return 是否过期  */ public Boolean isTokenExpired(String token) {  try {   Claims claims = getClaimsFromToken(token);   Date expiration = claims.getExpiration();   return expiration.before(new Date());  } catch (Exception e) {   return false;  } } /**  * 刷新令牌  *  * @param token 原令牌  * @return 新令牌  */ public String refreshToken(String token) {  String refreshedToken;  try {   Claims claims = getClaimsFromToken(token);   claims.put("created", new Date());   refreshedToken = generateToken(claims);  } catch (Exception e) {   refreshedToken = null;  }  return refreshedToken; } /**  * 验证令牌  *  * @param token  令牌  * @param userDetails 用户  * @return 是否有效  */ public Boolean validateToken(String token, UserDetails userDetails) {  SysUser user = (SysUser) userDetails;  String username = getUsernameFromToken(token);  return (username.equals(user.getUsername()) && !isTokenExpired(token)); } /**  * 从claims生成令牌,如果看不懂就看谁调用它  *  * @param claims 数据声明  * @return 令牌  */ private String generateToken(Map<String, Object> claims) {  Date expirationDate = new Date(System.currentTimeMillis() + expiration);  return Jwts.builder().setClaims(claims)       .setExpiration(expirationDate)       .signWith(SignatureAlgorithm.HS512, secret)       .compact(); } /**  * 从令牌中获取数据声明,如果看不懂就看谁调用它  *  * @param token 令牌  * @return 数据声明  */ private Claims getClaimsFromToken(String token) {  Claims claims;  try {   claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();  } catch (Exception e) {   claims = null;  }  return claims; }}

上面的代码就是使用io.jsonwebtoken.jjwt提供的方法开发JWT令牌生成、刷新的工具类。

三、开发登录接口(获取Token的接口)

"/authentication"接口用于登录验证,并且生成JWT返回给客户端"/REFRESHTOKEN"接口用于刷新JWT,更新JWT令牌的有效期@RESTCONTROLLERPUBLIC CLASS JWTAUTHCONTROLLER {  @RESOURCE  PRIVATE JWTAUTHSERVICE JWTAUTHSERVICE;  @POSTMAPPING(VALUE = "/AUTHENTICATION")  PUBLIC AJAXRESPONSE LOGIN(@REQUESTBODY MAP<STRING, STRING> MAP) {    STRING USERNAME = MAP.GET("USERNAME");    STRING PASSWORD = MAP.GET("PASSWORD");    IF (STRINGUTILS.ISEMPTY(USERNAME) || STRINGUTILS.ISEMPTY(PASSWORD)) {      RETURN AJAXRESPONSE.ERROR(        NEW CUSTOMEXCEPTION(CUSTOMEXCEPTIONTYPE.USER_INPUT_ERROR,"用户名密码不能为空"));    }    RETURN AJAXRESPONSE.SUCCESS(JWTAUTHSERVICE.LOGIN(USERNAME, PASSWORD));  }  @POSTMAPPING(VALUE = "/REFRESHTOKEN")  PUBLIC AJAXRESPONSE REFRESH(@REQUESTHEADER("${JWT.HEADER}") STRING TOKEN) {    RETURN AJAXRESPONSE.SUCCESS(JWTAUTHSERVICE.REFRESHTOKEN(TOKEN));  }}

核心的token业务逻辑写在JwtAuthService 中

login方法中首先使用用户名、密码进行登录验证。如果验证失败抛出BadCredentialsException异常。如果验证成功,程序继续向下走,生成JWT响应给前端

refreshToken方法只有在JWT token没有过期的情况下才能刷新,过期了就不能刷新了。需要重新登录。

@Servicepublic class JwtAuthService {  @Resource  private AuthenticationManager authenticationManager;  @Resource  private UserDetailsService userDetailsService;  @Resource  private JwtTokenUtil jwtTokenUtil;  public String login(String username, String password) {    //使用用户名密码进行登录验证    UsernamePasswordAuthenticationToken upToken =           new UsernamePasswordAuthenticationToken( username, password );    Authentication authentication = authenticationManager.authenticate(upToken);     SecurityContextHolder.getContext().setAuthentication(authentication);    //生成JWT    UserDetails userDetails = userDetailsService.loadUserByUsername( username );    return jwtTokenUtil.generateToken(userDetails);  }  public String refreshToken(String oldToken) {    if (!jwtTokenUtil.isTokenExpired(oldToken)) {      return jwtTokenUtil.refreshToken(oldToken);    }    return null;  }}

因为使用到了AuthenticationManager ,所以在继承WebSecurityConfigurerAdapter的SpringSecurity配置实现类中,将AuthenticationManager 声明为一个Bean。并将"/authentication"和 "/refreshtoken"开放访问权限,如何开放访问权限,我们之前的文章已经讲过了。

@Bean(name = BeanIds.AUTHENTICATION_MANAGER)@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {  return super.authenticationManagerBean();}

四、接口访问鉴权过滤器

当用户第一次登陆之后,我们将JWT令牌返回给了客户端,客户端应该将该令牌保存起来。在进行接口请求的时候,将令牌带上,放到HTTP的header里面,header的名字要和jwt.header的配置一致,这样服务端才能解析到。下面我们定义一个拦截器:

拦截接口请求,从请求request获取token,从token中解析得到用户名

然后通过UserDetailsService获得系统用户(从数据库、或其他其存储介质)

根据用户信息和JWT令牌,验证系统用户与用户输入的一致性,并判断JWT是否过期。如果没有过期,至此表明了该用户的确是该系统的用户。

但是,你是系统用户不代表你可以访问所有的接口。所以需要构造UsernamePasswordAuthenticationToken传递用户、权限信息,并将这些信息通过authentication告知Spring Security。Spring Security会以此判断你的接口访问权限。

@Slf4j@Componentpublic class JwtAuthenticationTokenFilter extends OncePerRequestFilter {  @Resource  private MyUserDetailsService userDetailsService;  @Resource  private JwtTokenUtil jwtTokenUtil;  @Override  protected void doFilterInternal(HttpServletRequest request,                  HttpServletResponse response,                  FilterChain chain) throws ServletException, IOException {      // 从这里开始获取 request 中的 jwt token    String authHeader = request.getHeader(jwtTokenUtil.getHeader());    log.info("authHeader:{}", authHeader);    // 验证token是否存在    if (authHeader != null && StringUtils.isNotEmpty(authHeader)) {      // 根据token 获取用户名      String username = jwtTokenUtil.getUsernameFromToken(authHeader);      if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {        // 通过用户名 获取用户的信息        UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);                // 验证JWT是否过期        if (jwtTokenUtil.validateToken(authHeader, userDetails)) {          //加载用户、角色、权限信息,Spring Security根据这些信息判断接口的访问权限          UsernamePasswordAuthenticationToken authentication               = new UsernamePasswordAuthenticationToken(userDetails, null,                                    userDetails.getAuthorities());          authentication.setDetails(new WebAuthenticationDetailsSource()                      .buildDetails(request));          SecurityContextHolder.getContext().setAuthentication(authentication);        }      }    }    chain.doFilter(request, response);  }}

在spring Security的配置类(即WebSecurityConfigurerAdapter实现类的configure(HttpSecurity http)配置方法中,加入如下配置:

.sessionManagement()  .sessionCreationPolicy(SessionCreationPolicy.STATELESS)  .and().addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

因为我们使用了JWT,表明了我们的应用是一个前后端分离的应用,所以我们可以开启STATELESS禁止使用session。当然这并不绝对,前后端分离的应用通过一些办法也是可以使用session的,这不是本文的核心内容不做赘述。将我们的自定义jwtAuthenticationTokenFilter,加载到UsernamePasswordAuthenticationFilter的前面。

五、测试一下:

测试登录接口,即:获取token的接口。输入正确的用户名、密码即可获取token。

下面我们访问一个我们定义的简单的接口“/hello”,但是不传递JWT令牌,结果是禁止访问。当我们将上一步返回的token,传递到header中,就能正常响应hello的接口结果。

以上所述是小编给大家介绍的springboot以FTP方式上传文件到远程服务器的流程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

看完上述内容,你们对springboot怎么以FTP方式上传文件到远程服务器有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI