接口能创建对象吗,STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)

 2023-09-26 阅读 30 评论 0

摘要:STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理) 1.项目创建 1、新建工程 2、选择打包方式,这边可以选择为打包为Jar包,或者传统的打包为War包 3、选择开发过程中使用到的技术,这边我选

STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)

 

 

1.项目创建

 

1、新建工程

 

 

2、选择打包方式,这边可以选择为打包为Jar包,或者传统的打包为War包

 

3、选择开发过程中使用到的技术,这边我选择的是Rest Repositories

 

4、新建测试用Controller

 

    文件内容如下

 

[java] view plain copy

  1. package com.xiaofangtech.example;  
  2.   
  3. import org.springframework.web.bind.annotation.RequestMapping;  
  4. import org.springframework.web.bind.annotation.RestController;  
  5.   
  6. @RestController  
  7. public class HelloController {  
  8.     @RequestMapping("/greeting")  
  9.     public String hello()  
  10.     {  
  11.         return "Hello world";  
  12.     }  
  13. }  


5、以Srping Boot App 方式运行

 

 

正常运行后控制台如下

 

6、测试运行

至此,一个最简单的hello world的工程创建运行完成

 

7、打包部署

   7.1 打包为可运行jar包

   使用mvn package 进行打包

   

 

 然后run ,运行成功后如下生成jar包

 

 

 

 7.2 打包为传统的war包 

       当第2步中选择的打包方式为war时,执行7.1中mvn package时,生成的包就是war包

     

 

 

运行war包跟运行jar包一样,找到war包所在目录,注解运行war包

 

D:\new_tech\spring-suite-tool\workspace\workspace1\demo1\target>java -jar demo1-0.0.1-SNAPSHOT.war

 

访问服务接口: localhost:8080/greeting

 

 

2.代码实现连接数据实现Rest接口和Basic 基础认证

0.引入pom依赖

 

 
  1. <dependency>

  2. <groupId>org.projectlombok</groupId>

  3. <artifactId>lombok</artifactId>

  4. </dependency>

  5.  
  6. <!-- 使用MySQL数据库,并用Spring Data JPA来作为数据库访问 -->

  7. <dependency>

  8. <groupId>org.springframework.boot</groupId>

  9. <artifactId>spring-boot-starter-data-jpa</artifactId>

  10. </dependency>

  11. <dependency>

  12. <groupId>mysql</groupId>

  13. <artifactId>mysql-connector-java</artifactId>

  14. </dependency>

 

 

 

1.代码整体结构

 

 

2.注册Filter过滤器的两种方式:

        1.在自定义的Filter上使用注解:

           

 
  1. /*

  2. * Filter实现简单的Http Basic 认证

  3. */

  4. @Component

  5. @WebFilter(filterName = "httpBasicAuthorizedFilter", urlPatterns="/user/*")

  6. public class HttpBasicAuthorizeFilter implements Filter {

 

       2.在配置类中定义Filter

 

 
  1. @Bean

  2. public FilterRegistrationBean filterRegistrationBean() {

  3. FilterRegistrationBean registrationBean = new FilterRegistrationBean();

  4. HttpBasicAuthorizeFilter httpBasicFilter = new HttpBasicAuthorizeFilter();

  5. registrationBean.setFilter(httpBasicFilter);

  6. List<String> urlPatterns = new ArrayList<String>();

  7. urlPatterns.add("/user/*");

  8. registrationBean.setUrlPatterns(urlPatterns);

  9. return registrationBean;

  10. }

 

3.数据库和Rest接口操作效果展示:

 

 

4.过滤器效果展示

  

代码中固定用户名密码都为test,所以对接口进行请求时,需要添加以下认证头信息

Authorization: Basic dGVzdDp0ZXN0

dGVzdDp0ZXN0 为 test:test 经过base64编码后的结果

 

如果未添加认证信息或者认证信息错误,返回没有权限的错误信息

 

 

当认证信息正确,返回请求结果

 

3.自定义Properties解析类和分布式Token JWT用户校验

    1.自定义Properties解析类的使用规则

                  1.定义Properties配置文件   ---- jwt.properties

                      

 
  1. jwt.info.clientId=098f6bcd4621d373cade4e832627b4f6

  2. jwt.info.base64Secret=MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=

  3. jwt.info.name=restapiuser

  4. jwt.info.expiresSecond=172800

 

 

                  2.自定义解析类                      ---- JwtInfo.java  指定配置文件地址和配置前缀,属性是前缀之后的名称

 
  1. package com.jay.properties;

  2.  
  3. import org.springframework.boot.context.properties.ConfigurationProperties;

  4. /*

  5. * 自定义配置文件的解析类

  6. */

  7. @ConfigurationProperties(prefix = "jwt.info", locations = "classpath:/config/jwt.properties")

  8. public class JwtInfo {

  9. private String clientId;

  10. private String base64Secret;

  11. private String name;

  12. private int expiresSecond;

  13. public String getClientId() {

  14. return clientId;

  15. }

  16. public void setClientId(String clientId) {

  17. this.clientId = clientId;

  18. }

  19. public String getBase64Secret() {

  20. return base64Secret;

  21. }

  22. public void setBase64Secret(String base64Secret) {

  23. this.base64Secret = base64Secret;

  24. }

  25. public String getName() {

  26. return name;

  27. }

  28. public void setName(String name) {

  29. this.name = name;

  30. }

  31. public int getExpiresSecond() {

  32. return expiresSecond;

  33. }

  34. public void setExpiresSecond(int expiresSecond) {

  35. this.expiresSecond = expiresSecond;

  36. }

  37.  
  38. }

 

 

                  3.启动类或配置类中,指定自定义Properties解析类

 
  1. package com.jay;

  2.  
  3. import org.springframework.boot.SpringApplication;

  4. import org.springframework.boot.autoconfigure.SpringBootApplication;

  5. import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties.Jwt;

  6. import org.springframework.boot.context.properties.EnableConfigurationProperties;

  7. import org.springframework.boot.web.servlet.ServletComponentScan;

  8.  
  9. import com.jay.properties.JwtInfo;

  10.  
  11. @SpringBootApplication

  12. @EnableConfigurationProperties(JwtInfo.class) //加载自定义的properties解析类

  13. public class Demo1Application {

  14.  
  15. public static void main(String[] args) {

  16. SpringApplication.run(Demo1Application.class, args);

  17. }

  18. }

 

               4.输出配置文件信息         ---- JwtInfoController.java

 

 
  1. package com.jay.controller;

  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;

  4. import org.springframework.web.bind.annotation.RequestMapping;

  5. import org.springframework.web.bind.annotation.RequestMethod;

  6. import org.springframework.web.bind.annotation.RestController;

  7.  
  8. import com.jay.properties.JwtInfo;

  9. import com.jay.vo.ResultMsg;

  10. import com.jay.vo.ResultStatusCode;

  11.  
  12. @RestController

  13. @RequestMapping("/jwt")

  14. public class JwtInfoController {

  15.  
  16. @Autowired

  17. private JwtInfo jwtInfo;

  18.  
  19. @RequestMapping(value = "/info", method = RequestMethod.GET)

  20. public Object getJwtInfo() {

  21. return new ResultMsg<JwtInfo>(true, ResultStatusCode.OK.getErrorCode(), ResultStatusCode.OK.getErrorMsg(), jwtInfo);

  22. }

  23. }


               5.效果展示

              


 

          2.使用分布式token  JWT进行用户认证

 

              

jwt(json web token)

用户发送按照约定,向服务端发送 Header、Payload 和 Signature,并包含认证信息(密码),验证通过后服务端返回一个token,之后用户使用该token作为登录凭证,适合于移动端和api

 

jwt使用流程

 

              1.添加 JWT依赖

 
  1. <!-- JWT Json Web Token 依赖 -->

  2. <dependency>

  3. <groupId>io.jsonwebtoken</groupId>

  4. <artifactId>jjwt</artifactId>

  5. <version>0.7.0</version>

  6. </dependency>


             2.编写Jwt解析类和Jwt过滤器

             

 
  1. package com.jay.util.jwt;

  2.  
  3. import java.security.Key;

  4. import java.util.Date;

  5.  
  6. import javax.crypto.spec.SecretKeySpec;

  7. import javax.xml.bind.DatatypeConverter;

  8.  
  9. import io.jsonwebtoken.Claims;

  10. import io.jsonwebtoken.JwtBuilder;

  11. import io.jsonwebtoken.Jwts;

  12. import io.jsonwebtoken.SignatureAlgorithm;

  13.  
  14. /*

  15. * 构造及解析jwt的工具类

  16. */

  17. public class JwtHelper {

  18. public static Claims parseJWT(String jsonWebToken, String base64Security){

  19. try

  20. {

  21. Claims claims = Jwts.parser()

  22. .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))

  23. .parseClaimsJws(jsonWebToken).getBody();

  24. return claims;

  25. }

  26. catch(Exception ex)

  27. {

  28. return null;

  29. }

  30. }

  31.  
  32. /**

  33. * 生成token

  34. *

  35. * @author hetiewei

  36. * @date 2016年10月18日 下午2:51:38

  37. * @param name keyId

  38. * @param userId

  39. * @param role

  40. * @param audience 接收者

  41. * @param issuer 发行者

  42. * @param TTLMillis 过期时间(毫秒)

  43. * @param base64Security

  44. * @return

  45. */

  46. public static String createJWT(String name, String userId, String role,

  47. String audience, String issuer, long TTLMillis, String base64Security)

  48. {

  49. SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

  50.  
  51. long nowMillis = System.currentTimeMillis();

  52. Date now = new Date(nowMillis);

  53.  
  54. //生成签名密钥

  55. byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);

  56. Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

  57.  
  58. //添加构成JWT的参数

  59. JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")

  60. .claim("role", role)

  61. .claim("unique_name", name)

  62. .claim("userid", userId)

  63. .setIssuer(issuer)

  64. .setAudience(audience)

  65. .signWith(signatureAlgorithm, signingKey);

  66. //添加Token过期时间

  67. if (TTLMillis >= 0) {

  68. long expMillis = nowMillis + TTLMillis;

  69. Date exp = new Date(expMillis);

  70. builder.setExpiration(exp).setNotBefore(now);

  71. }

  72.  
  73. //生成JWT

  74. return builder.compact();

  75. }

  76. }

 

 

 

 
  1. package com.jay.filter;

  2.  
  3. import java.io.IOException;

  4.  
  5. import javax.servlet.Filter;

  6. import javax.servlet.FilterChain;

  7. import javax.servlet.FilterConfig;

  8. import javax.servlet.ServletException;

  9. import javax.servlet.ServletRequest;

  10. import javax.servlet.ServletResponse;

  11. import javax.servlet.http.HttpServletRequest;

  12. import javax.servlet.http.HttpServletResponse;

  13.  
  14. import org.springframework.beans.factory.annotation.Autowired;

  15. import org.springframework.web.context.support.SpringBeanAutowiringSupport;

  16.  
  17. import com.fasterxml.jackson.databind.ObjectMapper;

  18. import com.jay.properties.JwtInfo;

  19. import com.jay.util.jwt.JwtHelper;

  20. import com.jay.vo.ResultMsg;

  21. import com.jay.vo.ResultStatusCode;

  22.  
  23. /*

  24. * 用于JWT认证的过滤器

  25. */

  26. public class JwtAuthorizeFilter implements Filter{

  27.  
  28. /*

  29. * 注入配置文件类

  30. */

  31. @Autowired

  32. private JwtInfo jwtInfo;

  33.  
  34. @Override

  35. public void destroy() {

  36.  
  37. }

  38.  
  39. @Override

  40. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

  41. throws IOException, ServletException {

  42. ResultMsg<Object> resultMsg;

  43. HttpServletRequest httpRequest = (HttpServletRequest)request;

  44. String auth = httpRequest.getHeader("Authorization");

  45. if ((auth != null) && (auth.length() > 7))

  46. {

  47. String HeadStr = auth.substring(0, 6).toLowerCase();

  48. if (HeadStr.compareTo("bearer") == 0)

  49. {

  50.  
  51. auth = auth.substring(7, auth.length());

  52. if (JwtHelper.parseJWT(auth, jwtInfo.getBase64Secret()) != null)

  53. {

  54. chain.doFilter(request, response);

  55. return;

  56. }

  57. }

  58. }

  59.  
  60. //验证不通过

  61. HttpServletResponse httpResponse = (HttpServletResponse) response;

  62. httpResponse.setCharacterEncoding("UTF-8");

  63. httpResponse.setContentType("application/json; charset=utf-8");

  64. httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

  65.  
  66. //将验证不通过的错误返回

  67. ObjectMapper mapper = new ObjectMapper();

  68.  
  69. resultMsg = new ResultMsg<Object>(true, ResultStatusCode.INVALID_TOKEN.getErrorCode(), ResultStatusCode.INVALID_TOKEN.getErrorMsg(), null);

  70. httpResponse.getWriter().write(mapper.writeValueAsString(resultMsg));

  71. return;

  72. }

  73.  
  74. @Override

  75. public void init(FilterConfig filterConfig) throws ServletException {

  76. SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());

  77. }

  78.  
  79. }

 

 

 

 

 

 

            3.在Jwt配置类中,添加过滤器

             

 
  1. package com.jay.config;

  2.  
  3. import java.util.ArrayList;

  4. import java.util.List;

  5.  
  6. import org.springframework.boot.context.embedded.FilterRegistrationBean;

  7. import org.springframework.context.annotation.Bean;

  8. import org.springframework.context.annotation.Configuration;

  9.  
  10. import com.jay.filter.JwtAuthorizeFilter;

  11.  
  12.  
  13. /*

  14. * 注册jwt认证过滤器

  15. */

  16. @Configuration

  17. public class JwtConfig {

  18.  
  19. /*

  20. * 注册过滤器类和过滤的url

  21. */

  22. @Bean

  23. public FilterRegistrationBean basicFilterRegistrationBean(){

  24. FilterRegistrationBean registrationBean = new FilterRegistrationBean();

  25. JwtAuthorizeFilter filter = new JwtAuthorizeFilter();

  26. registrationBean.setFilter(filter);

  27.  
  28. List<String> urlPatterns = new ArrayList<>();

  29. urlPatterns.add("/user/*");

  30.  
  31. registrationBean.setUrlPatterns(urlPatterns);

  32. return registrationBean;

  33. }

  34. }

 

            

            4.效果展示:

                       1. 获取token,传入用户认证信息

 

 

 

 

                    2.使用上面获取的token进行接口调用,     未使用token,获取token错误,或者token过期时

 

 

               3.使用正确的token时

                   

                    

 

 

 

特别注意:

              JWT使用时,可以通过Cookie机制,自动的传递!!!

 

 

4.Redis + Cookie 机制,进行验证码的校验

 

1.添加redis和captcha库依赖

 

 
  1. <!-- 整合redis -->

  2. <dependency>

  3. <groupId>org.springframework.boot</groupId>

  4. <artifactId>spring-boot-starter-redis</artifactId>

  5. </dependency>

  6. <!-- 第三方验证码库 -->

  7. <dependency>

  8. <groupId>cn.apiclub.tool</groupId>

  9. <artifactId>simplecaptcha</artifactId>

  10. <version>1.2.2</version>

  11. </dependency>

 

2.redis配置

 

 
  1. ##Redis配置

  2. spring.redis.database=1

  3. spring.redis.host=localhost

  4. #spring.redis.password=password

  5. spring.redis.port=6379

  6. spring.redis.timeout=2000

  7. spring.redis.pool.max-idle=8

  8. spring.redis.pool.min-idle=0

  9. spring.redis.pool.max-active=8

  10. spring.redis.pool.max-wait=-1

 

3.Redis配置类,实例化Redis模板

 

 
  1. package com.jay.config;

  2.  
  3. import org.springframework.context.annotation.Bean;

  4. import org.springframework.context.annotation.Configuration;

  5. import org.springframework.data.redis.connection.RedisConnectionFactory;

  6. import org.springframework.data.redis.core.RedisTemplate;

  7. import org.springframework.data.redis.core.StringRedisTemplate;

  8. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

  9.  
  10. import com.fasterxml.jackson.annotation.JsonAutoDetect;

  11. import com.fasterxml.jackson.annotation.PropertyAccessor;

  12. import com.fasterxml.jackson.databind.ObjectMapper;

  13.  
  14. @Configuration

  15. public class RedisConfig {

  16.  
  17. // 定义Redis模板

  18. @Bean

  19. public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {

  20. StringRedisTemplate template = new StringRedisTemplate(factory);

  21. // 设置序列化工具, 这样缓存的Bean就不需要再试下Serializable接口

  22. setSerrializer(template);

  23. template.afterPropertiesSet();

  24. return template;

  25. }

  26.  
  27. // 设置序列化

  28. private void setSerrializer(StringRedisTemplate template) {

  29. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

  30. ObjectMapper om = new ObjectMapper();

  31. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

  32. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

  33. jackson2JsonRedisSerializer.setObjectMapper(om);

  34. template.setValueSerializer(jackson2JsonRedisSerializer);

  35. }

  36. }

 

4.Controller层操作代码

 

 
  1. package com.jay.controller;

  2.  
  3. import java.io.ByteArrayOutputStream;

  4. import java.io.IOException;

  5. import java.util.UUID;

  6. import java.util.concurrent.TimeUnit;

  7.  
  8. import javax.imageio.ImageIO;

  9. import javax.servlet.http.Cookie;

  10. import javax.servlet.http.HttpServletRequest;

  11. import javax.servlet.http.HttpServletResponse;

  12.  
  13. import org.springframework.beans.factory.annotation.Autowired;

  14. import org.springframework.data.redis.core.RedisTemplate;

  15. import org.springframework.http.HttpRequest;

  16. import org.springframework.http.MediaType;

  17. import org.springframework.stereotype.Controller;

  18. import org.springframework.web.bind.annotation.PathVariable;

  19. import org.springframework.web.bind.annotation.RequestMapping;

  20. import org.springframework.web.bind.annotation.RequestMethod;

  21. import org.springframework.web.bind.annotation.ResponseBody;

  22.  
  23. import com.jay.util.CookieUtils;

  24. import com.jay.vo.ResultMsg;

  25. import com.jay.vo.ResultStatusCode;

  26.  
  27. import cn.apiclub.captcha.Captcha;

  28. import cn.apiclub.captcha.backgrounds.GradiatedBackgroundProducer;

  29. import cn.apiclub.captcha.gimpy.FishEyeGimpyRenderer;

  30. import io.swagger.annotations.ApiOperation;

  31.  
  32. @Controller

  33. @RequestMapping("/redis")

  34. public class RedisCaptchaController {

  35.  
  36. @Autowired

  37. private RedisTemplate<String, String> redisTemplate;

  38.  
  39. private static int captchaExpires = 3 * 60; // 超时时间3min,验证码超时,自动冲redis中删除

  40. private static int captchaW = 200;

  41. private static int captchaH = 60;

  42. private static String cookieName = "CaptchaCode";

  43.  
  44. @RequestMapping(value = "getcaptcha", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)

  45. public @ResponseBody byte[] getCaptcha(HttpServletResponse response) {

  46. // 生成验证码

  47. String uuid = UUID.randomUUID().toString();

  48. Captcha captcha = new Captcha.Builder(captchaW, captchaH).addText()

  49. .addBackground(new GradiatedBackgroundProducer()).gimp(new FishEyeGimpyRenderer()).build();

  50.  
  51. // 将验证码以<key,value>形式缓存到redis

  52. redisTemplate.opsForValue().set(uuid, captcha.getAnswer(), captchaExpires, TimeUnit.SECONDS);

  53.  
  54. // 将验证码key,及验证码的图片返回

  55. Cookie cookie = new Cookie(cookieName, uuid);

  56. response.addCookie(cookie);

  57. ByteArrayOutputStream bao = new ByteArrayOutputStream();

  58. try {

  59. ImageIO.write(captcha.getImage(), "png", bao);

  60. return bao.toByteArray();

  61. } catch (IOException e) {

  62. return null;

  63. }

  64. }

  65.  
  66. /*

  67. * 说明:

  68. * 1.captchaCode来自客户端的Cookie,在访问时,通过服务端设置

  69. * 2.captcha是用户填写的验证码,将用户填写的验证码和通过captchaCode从redis中获取的验证码进行对比即可

  70. *

  71. */

  72. @ApiOperation(value = "验证码校验")

  73. @RequestMapping(value = "/captcha/check/{captcha}")

  74. @ResponseBody

  75. public ResultMsg<Object> checkCaptcha(@PathVariable("captcha") String captcha, HttpServletRequest request){

  76.  
  77. String captchaCode = CookieUtils.getCookie(request, cookieName);

  78.  
  79. ResultMsg<Object> result;

  80.  
  81. try{

  82. if (captcha == null)

  83. {

  84. throw new Exception();

  85. }

  86.  
  87. //redis中查询验证码

  88. String captchaValue = redisTemplate.opsForValue().get(captchaCode);

  89.  
  90. if (captchaValue == null) {

  91. throw new Exception();

  92. }

  93.  
  94. if (captchaValue.compareToIgnoreCase(captcha) != 0) {

  95. throw new Exception();

  96. }

  97.  
  98. //验证码匹配成功,redis则删除对应的验证码

  99. redisTemplate.delete(captchaCode);

  100.  
  101. return new ResultMsg<Object>(true, ResultStatusCode.OK.getErrorCode(), ResultStatusCode.OK.getErrorMsg(), null);

  102.  
  103. }catch (Exception e) {

  104. result = new ResultMsg<Object>(false, ResultStatusCode.INVALID_CAPTCHA.getErrorCode(), ResultStatusCode.INVALID_CAPTCHA.getErrorMsg(), null);

  105. }

  106. return result;

  107. }

  108.  
  109.  
  110. }

 

5.效果展示

 

1.访问生成验证码

 

 

2.验证验证码

 

 

项目源码下载:下载地址

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/97913.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息