STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)
来源:互联网 发布:五线谱转吉他谱软件 编辑:程序博客网 时间:2024/05/17 13:42
1.项目创建
1、新建工程
2、选择打包方式,这边可以选择为打包为Jar包,或者传统的打包为War包
3、选择开发过程中使用到的技术,这边我选择的是Rest Repositories
4、新建测试用Controller
文件内容如下
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 基础认证
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- 使用MySQL数据库,并用Spring Data JPA来作为数据库访问 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>
/* * Filter实现简单的Http Basic 认证 */@Component@WebFilter(filterName = "httpBasicAuthorizedFilter", urlPatterns="/user/*")public class HttpBasicAuthorizeFilter implements Filter {
@Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); HttpBasicAuthorizeFilter httpBasicFilter = new HttpBasicAuthorizeFilter(); registrationBean.setFilter(httpBasicFilter); List<String> urlPatterns = new ArrayList<String>(); urlPatterns.add("/user/*"); registrationBean.setUrlPatterns(urlPatterns); return registrationBean; }
Authorization: Basic dGVzdDp0ZXN0
dGVzdDp0ZXN0 为 test:test 经过base64编码后的结果
如果未添加认证信息或者认证信息错误,返回没有权限的错误信息
当认证信息正确,返回请求结果
3.自定义Properties解析类和分布式Token JWT用户校验
1.自定义Properties解析类的使用规则
jwt.info.clientId=098f6bcd4621d373cade4e832627b4f6jwt.info.base64Secret=MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=jwt.info.name=restapiuserjwt.info.expiresSecond=172800
package com.jay.properties;import org.springframework.boot.context.properties.ConfigurationProperties;/* * 自定义配置文件的解析类 */@ConfigurationProperties(prefix = "jwt.info", locations = "classpath:/config/jwt.properties")public class JwtInfo {private String clientId; private String base64Secret; private String name; private int expiresSecond;public String getClientId() {return clientId;}public void setClientId(String clientId) {this.clientId = clientId;}public String getBase64Secret() {return base64Secret;}public void setBase64Secret(String base64Secret) {this.base64Secret = base64Secret;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getExpiresSecond() {return expiresSecond;}public void setExpiresSecond(int expiresSecond) {this.expiresSecond = expiresSecond;}}
package com.jay;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties.Jwt;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.boot.web.servlet.ServletComponentScan;import com.jay.properties.JwtInfo;@SpringBootApplication@EnableConfigurationProperties(JwtInfo.class) //加载自定义的properties解析类public class Demo1Application {public static void main(String[] args) {SpringApplication.run(Demo1Application.class, args);}}
package com.jay.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import com.jay.properties.JwtInfo;import com.jay.vo.ResultMsg;import com.jay.vo.ResultStatusCode;@RestController@RequestMapping("/jwt")public class JwtInfoController {@Autowiredprivate JwtInfo jwtInfo;@RequestMapping(value = "/info", method = RequestMethod.GET)public Object getJwtInfo() {return new ResultMsg<JwtInfo>(true, ResultStatusCode.OK.getErrorCode(), ResultStatusCode.OK.getErrorMsg(), jwtInfo);}}
5.效果展示
2.使用分布式token JWT进行用户认证
jwt(json web token)
用户发送按照约定,向服务端发送 Header、Payload 和 Signature,并包含认证信息(密码),验证通过后服务端返回一个token,之后用户使用该token作为登录凭证,适合于移动端和api
jwt使用流程
<!-- JWT Json Web Token 依赖 --><dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.7.0</version></dependency>
2.编写Jwt解析类和Jwt过滤器
package com.jay.util.jwt;import java.security.Key;import java.util.Date;import javax.crypto.spec.SecretKeySpec;import javax.xml.bind.DatatypeConverter;import io.jsonwebtoken.Claims;import io.jsonwebtoken.JwtBuilder;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;/* * 构造及解析jwt的工具类 */public class JwtHelper {public static Claims parseJWT(String jsonWebToken, String base64Security){try{Claims claims = Jwts.parser() .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security)) .parseClaimsJws(jsonWebToken).getBody();return claims;}catch(Exception ex){return null;}}/** * 生成token * * @author hetiewei * @date 2016年10月18日 下午2:51:38 * @param name keyId * @param userId * @param role * @param audience 接收者 * @param issuer 发行者 * @param TTLMillis 过期时间(毫秒) * @param base64Security * @return */public static String createJWT(String name, String userId, String role, String audience, String issuer, long TTLMillis, String base64Security) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis); //生成签名密钥byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName()); //添加构成JWT的参数JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT").claim("role", role) .claim("unique_name", name) .claim("userid", userId) .setIssuer(issuer) .setAudience(audience) .signWith(signatureAlgorithm, signingKey); //添加Token过期时间if (TTLMillis >= 0) { long expMillis = nowMillis + TTLMillis; Date exp = new Date(expMillis); builder.setExpiration(exp).setNotBefore(now);} //生成JWTreturn builder.compact();} }
package com.jay.filter;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.context.support.SpringBeanAutowiringSupport;import com.fasterxml.jackson.databind.ObjectMapper;import com.jay.properties.JwtInfo;import com.jay.util.jwt.JwtHelper;import com.jay.vo.ResultMsg;import com.jay.vo.ResultStatusCode;/* * 用于JWT认证的过滤器 */public class JwtAuthorizeFilter implements Filter{/* * 注入配置文件类 */@Autowiredprivate JwtInfo jwtInfo;@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException { ResultMsg<Object> resultMsg; HttpServletRequest httpRequest = (HttpServletRequest)request; String auth = httpRequest.getHeader("Authorization"); if ((auth != null) && (auth.length() > 7)) { String HeadStr = auth.substring(0, 6).toLowerCase(); if (HeadStr.compareTo("bearer") == 0) { auth = auth.substring(7, auth.length()); if (JwtHelper.parseJWT(auth, jwtInfo.getBase64Secret()) != null) { chain.doFilter(request, response); return; } } } //验证不通过 HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setCharacterEncoding("UTF-8"); httpResponse.setContentType("application/json; charset=utf-8"); httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); //将验证不通过的错误返回 ObjectMapper mapper = new ObjectMapper(); resultMsg = new ResultMsg<Object>(true, ResultStatusCode.INVALID_TOKEN.getErrorCode(), ResultStatusCode.INVALID_TOKEN.getErrorMsg(), null); httpResponse.getWriter().write(mapper.writeValueAsString(resultMsg)); return; }@Overridepublic void init(FilterConfig filterConfig) throws ServletException {SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());}}
package com.jay.config;import java.util.ArrayList;import java.util.List;import org.springframework.boot.context.embedded.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import com.jay.filter.JwtAuthorizeFilter;/* * 注册jwt认证过滤器 */@Configurationpublic class JwtConfig {/* * 注册过滤器类和过滤的url */@Beanpublic FilterRegistrationBean basicFilterRegistrationBean(){FilterRegistrationBean registrationBean = new FilterRegistrationBean();JwtAuthorizeFilter filter = new JwtAuthorizeFilter();registrationBean.setFilter(filter);List<String> urlPatterns = new ArrayList<>();urlPatterns.add("/user/*");registrationBean.setUrlPatterns(urlPatterns);return registrationBean;}}
4.Redis + Cookie 机制,进行验证码的校验
<!-- 整合redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> <!-- 第三方验证码库 --><dependency> <groupId>cn.apiclub.tool</groupId> <artifactId>simplecaptcha</artifactId> <version>1.2.2</version></dependency>
##Redis配置spring.redis.database=1spring.redis.host=localhost#spring.redis.password=passwordspring.redis.port=6379spring.redis.timeout=2000spring.redis.pool.max-idle=8spring.redis.pool.min-idle=0spring.redis.pool.max-active=8spring.redis.pool.max-wait=-1
package com.jay.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;@Configurationpublic class RedisConfig {// 定义Redis模板@Beanpublic RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {StringRedisTemplate template = new StringRedisTemplate(factory);// 设置序列化工具, 这样缓存的Bean就不需要再试下Serializable接口setSerrializer(template);template.afterPropertiesSet();return template;}// 设置序列化private void setSerrializer(StringRedisTemplate template) {Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);template.setValueSerializer(jackson2JsonRedisSerializer);}}
package com.jay.controller;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.UUID;import java.util.concurrent.TimeUnit;import javax.imageio.ImageIO;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.http.HttpRequest;import org.springframework.http.MediaType;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import com.jay.util.CookieUtils;import com.jay.vo.ResultMsg;import com.jay.vo.ResultStatusCode;import cn.apiclub.captcha.Captcha;import cn.apiclub.captcha.backgrounds.GradiatedBackgroundProducer;import cn.apiclub.captcha.gimpy.FishEyeGimpyRenderer;import io.swagger.annotations.ApiOperation;@Controller@RequestMapping("/redis")public class RedisCaptchaController {@Autowiredprivate RedisTemplate<String, String> redisTemplate;private static int captchaExpires = 3 * 60; // 超时时间3min,验证码超时,自动冲redis中删除private static int captchaW = 200;private static int captchaH = 60;private static String cookieName = "CaptchaCode";@RequestMapping(value = "getcaptcha", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)public @ResponseBody byte[] getCaptcha(HttpServletResponse response) {// 生成验证码String uuid = UUID.randomUUID().toString();Captcha captcha = new Captcha.Builder(captchaW, captchaH).addText().addBackground(new GradiatedBackgroundProducer()).gimp(new FishEyeGimpyRenderer()).build();// 将验证码以<key,value>形式缓存到redisredisTemplate.opsForValue().set(uuid, captcha.getAnswer(), captchaExpires, TimeUnit.SECONDS);// 将验证码key,及验证码的图片返回Cookie cookie = new Cookie(cookieName, uuid);response.addCookie(cookie);ByteArrayOutputStream bao = new ByteArrayOutputStream();try {ImageIO.write(captcha.getImage(), "png", bao);return bao.toByteArray();} catch (IOException e) {return null;}}/* * 说明: * 1.captchaCode来自客户端的Cookie,在访问时,通过服务端设置 * 2.captcha是用户填写的验证码,将用户填写的验证码和通过captchaCode从redis中获取的验证码进行对比即可 * */@ApiOperation(value = "验证码校验")@RequestMapping(value = "/captcha/check/{captcha}")@ResponseBodypublic ResultMsg<Object> checkCaptcha(@PathVariable("captcha") String captcha, HttpServletRequest request){String captchaCode = CookieUtils.getCookie(request, cookieName);ResultMsg<Object> result;try{if (captcha == null) { throw new Exception(); } //redis中查询验证码String captchaValue = redisTemplate.opsForValue().get(captchaCode);if (captchaValue == null) {throw new Exception();}if (captchaValue.compareToIgnoreCase(captcha) != 0) {throw new Exception();}//验证码匹配成功,redis则删除对应的验证码 redisTemplate.delete(captchaCode);return new ResultMsg<Object>(true, ResultStatusCode.OK.getErrorCode(), ResultStatusCode.OK.getErrorMsg(), null);}catch (Exception e) {result = new ResultMsg<Object>(false, ResultStatusCode.INVALID_CAPTCHA.getErrorCode(), ResultStatusCode.INVALID_CAPTCHA.getErrorMsg(), null);}return result;}}
- STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)
- STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)
- Spring Boot实战之Filter实现使用JWT进行接口认证 jwt(json web token) 用户发送按照约定,向服务端发送 Header、Payload 和 Signature,
- STS 新建一个spring-boot rest 项目
- 使用spring tool suite(STS)工具创建spring boot项目和出现错误后的处理
- Spring Boot实战之Filter实现使用JWT进行接口认证
- Spring Boot实战之Filter实现使用JWT进行接口认证
- spring boot AOP和spring boot统一异常处理
- Spring Boot实战之Rest接口开发及数据库基本操作
- Spring Boot实战之Rest接口开发及数据库基本操作
- Spring-Boot 统一异常处理
- Spring Boot 异常统一处理
- Spring boot统一异常处理
- spring boot项目实战:异常处理
- Spring Boot集成JWT&Spring Security进行接口安全认证
- Spring Boot:(四)统一日志处理
- spring boot @Aspect 统一日志处理
- 利用spring aop统一处理异常和打日志
- Android学习 (十七) 把GSON库添加Android studio项目中
- 学习笔记---C语言中全局变量,变量,常量的定义与使用
- XML的解析方法详解
- Perf性能统计
- Android 开发环境下载地址 -- 百度网盘 adt-bundle android-studio sdk adt 下载
- STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)
- TCP数据的传输过程
- 受限玻尔兹曼机基础教程<一>
- 高并发系统的设计及秒杀实践
- Promise特性总结
- 从中间点开始计算网格坐标
- cocoapods更新失败fatal: Not a git repository (or any of the parent directories): .git
- 发短信验证码的常见云通讯平台分析
- 手机的IMEI、MEID、ICCID、UDID、IMSI