Springboot 配置 Redis
-
pom 引入spring-boot-starter-data-redis 包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
propertites配置文件,配置redis信息
# Redis数据库索引(默认为0) spring.redis.database=0 # Redis服务器地址 spring.redis.host=127.0.0.1 # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password=root # 连接池最大连接数(使用负值表示没有限制) spring.redis.jedis.pool.max-active=20 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.jedis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.jedis.pool.max-idle=10 # 连接池中的最小空闲连接 spring.redis.jedis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=1000
-
设置redis的配置文件
/** * @Notes redis 配置 * @Date 2022/3/21 * @Time 12:21 * @Author smile */ @Configuration public class RedisConfig{ @Bean public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String,Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class); //redis的key template.setValueSerializer(jsonRedisSerializer); template.setKeySerializer(new StringRedisSerializer()); //hash的key template.setHashValueSerializer(jsonRedisSerializer); template.setHashKeySerializer(new StringRedisSerializer()); return template; } }
-
测试案例
@Autowired private RedisTemplate redisTemplate; @Test public void TestRedis() { redisTemplate.opsForValue().set("smile","易文杰"); System.out.println(redisTemplate.opsForValue().get("smile")); }
Springboot 配置 Jwt
-
pom 引入jwt依赖
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.18.3</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.33</version> </dependency>
-
设置jwt工具类
package com.smile.blog.utils.jwt; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTCreator; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import java.util.Calendar; import java.util.Map; import java.util.Objects; /** * @Notes * @Date 2022/3/18 * @Time 17:56 * @Author smile */ public class Jwt { /*** * 过期时间秒 默认过期时间 **/ public static final int EXPIRE = 60 * 24 * 60 * 60; /*** * 加密明文 **/ public static final String KEY = "6TvUubi2AD7wMFFfeN84pTjcxngz8sqraCLliknFBcn32y99cA1q7WDomJmX1BMF"; /*** * @Notes 获取到token值 * * @return java.lang.String * @author smile * @date 2022/3/21 * @time 14:58 **/ public static String token(Map<String,String> payload) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.SECOND,EXPIRE); JWTCreator.Builder builder = JWT.create(); if (!Objects.isNull(payload)) { payload.forEach(builder::withClaim); } return builder.withExpiresAt(calendar.getTime()) .sign(Algorithm.HMAC256(KEY)); } /*** * @Notes 验证token值 * @param token token值 * @author smile * @date 2022/3/16 * @time 18:21 **/ public static void verify(String token) { JWT.require(Algorithm.HMAC256(KEY)) .build() .verify(token); } /*** * @Notes 解析token * @param token token值 * @return DecodedJWT * @author smile * @date 2022/3/16 * @time 18:23 **/ public static DecodedJWT parse(String token) { return JWT.require(Algorithm.HMAC256(KEY)) .build() .verify(token); } }
-
测试案例
Map<String,String> map = new HashMap<String,String>(); map.put("userId","123"); System.out.println(Jwt.token(map));
测试结果如下所示:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NTMwNTQzNzIsInVzZXJJZCI6IjEyMyJ9.Xb4yPxbKGqtppI64buahcqTNn5m2uXASd5_ioZcMCRQ
Map<String,String> map = new HashMap<String,String>(); map.put("userId","123"); String res = Jwt.parse(token).getClaim("userId").toString(); System.out.println(res);
测试结果如下所示:
"123"
-
添加restfulApi响应
-
ApiResponse
package com.smile.blog.utils.response; import com.alibaba.fastjson.annotation.JSONField; /** * @Notes * @Date 2022/3/18 * @Time 11:31 * @Author smile */ public class ApiResponse <T>{ /** * 状态码 */ @JSONField(name = "code") private long code; /** * 提示消息 */ @JSONField(name = "message") private String message; /** * 接口返回数据 */ @JSONField(name = "data") private T data; /** * 接口状态码 */ @JSONField(name = "status") private String status; protected ApiResponse() { } public ApiResponse(long code, String message, T data, String status) { this.code = code; this.message = message; this.data = data; this.status = status; } public static <T> ApiResponse<T> success() { return new ApiResponse<T>(ResponseCode.SUCCESS.getCode(), ResponseCode.SUCCESS.getMessage(), null, ResponseCode.SUCCESS.getStatus()); } public static <T> ApiResponse<T> success(String message) { return new ApiResponse<T>(ResponseCode.SUCCESS.getCode(), message, null, ResponseCode.SUCCESS.getStatus()); } public static <T> ApiResponse<T> success(String message,T data) { return new ApiResponse<T>(ResponseCode.SUCCESS.getCode(), message, data, ResponseCode.SUCCESS.getStatus()); } public static <T> ApiResponse<T> success(String message,T data,long code) { return new ApiResponse<T>(code, message, data, ResponseCode.SUCCESS.getStatus()); } public static <T> ApiResponse<T> failed() { return new ApiResponse<T>(ResponseCode.FAILED.getCode(), ResponseCode.FAILED.getMessage(), null, ResponseCode.FAILED.getStatus()); } public static <T> ApiResponse<T> failed(String message) { return new ApiResponse<T>(ResponseCode.FAILED.getCode(), message, null, ResponseCode.FAILED.getStatus()); } public static <T> ApiResponse<T> failed(String message,T data) { return new ApiResponse<T>(ResponseCode.FAILED.getCode(), message, data, ResponseCode.FAILED.getStatus()); } public static <T> ApiResponse<T> failed(String message,T data,long code) { return new ApiResponse<T>(code, message, data, ResponseCode.FAILED.getStatus()); } public static <T> ApiResponse<T> error(T data) { return new ApiResponse<T>(ResponseCode.ERROR.getCode(), ResponseCode.ERROR.getMessage(), null, ResponseCode.ERROR.getStatus()); } public static <T> ApiResponse<T> valid() { return new ApiResponse<T>(ResponseCode.VALIDATE_FAILED.getCode(), ResponseCode.VALIDATE_FAILED.getMessage(), null, ResponseCode.VALIDATE_FAILED.getStatus()); } public static <T> ApiResponse<T> valid(String message) { return new ApiResponse<T>(ResponseCode.VALIDATE_FAILED.getCode(), message, null, ResponseCode.VALIDATE_FAILED.getStatus()); } public long getCode() { return code; } public void setCode(long code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } }
-
IErrorCode
package com.smile.blog.utils.response; public interface IErrorCode { /*** * 返回状态码 **/ long getCode(); /*** * 返回状态值 **/ String getStatus(); /*** * 返回信息 **/ String getMessage(); }
-
ResponseCode
package com.smile.blog.utils.response; public enum ResponseCode implements IErrorCode{ SUCCESS(200,"成功","success"), FAILED(400,"失败","error"), UNAUTHORIZED(401,"身份验证失败","error"), VALIDATE_FAILED(402,"参数校验异常","error"), FORBIDDEN(403,"无权限访问","error"), NOT_FOUND(404,"路由未找到","error"), METHOD_NOT_ALLOWED (405,"请求方法不支持","error"), HTTP_TOO_MANY_REQUESTS(429,"接口频率限制","error"), ERROR(500,"系统异常","error"); /*** * 状态码 **/ private long code; /*** * 消息 **/ private String message; /*** * 状态值 **/ private String status; ResponseCode(long code, String message, String status) { this.code = code; this.message = message; this.status = status; } @Override public long getCode() { return code; } @Override public String getStatus() { return status; } @Override public String getMessage() { return message; } }
-
HttpResponse
package com.smile.blog.utils.response; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class HttpResponse { public static void response(HttpServletResponse response, String string) throws IOException { response.setStatus(200); response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); response.getWriter().print(string); } }
-
-
添加jwt过滤器
package com.smile.blog.filter; import com.alibaba.fastjson.JSON; import com.auth0.jwt.exceptions.AlgorithmMismatchException; import com.auth0.jwt.exceptions.SignatureVerificationException; import com.auth0.jwt.exceptions.TokenExpiredException; import com.smile.blog.utils.jwt.Jwt; import com.smile.blog.utils.response.ApiResponse; import com.smile.blog.utils.response.ResponseCode; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import javax.annotation.Resource; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Objects; /** * @Notes * jwt 过滤 验证token的有效性 * @Date 2022/3/18 * @Time 20:25 * @Author smile */ @Component public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { @Resource private RedisTemplate<String,String> redisTemplate; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = request.getHeader("authorization"); //判断token是否存在 if (!StringUtils.hasText(token)) { filterChain.doFilter(request,response); return; } //验证token是否正常 Object apiResponse = null; try { Jwt.verify(token); String payload = Jwt.parse(token).getClaim("userId").toString(); if (payload.isEmpty()) { apiResponse = ApiResponse.failed("身份验证失败",null, ResponseCode.UNAUTHORIZED.getCode()); } Object userCache = redisTemplate.opsForHash().get("users","user_"+payload); if (Objects.isNull(userCache) || userCache.toString().isEmpty()) { apiResponse = ApiResponse.failed("身份验证失败",null, ResponseCode.UNAUTHORIZED.getCode()); } //将信息存放于SecurityContextHolder filterChain.doFilter(request, response); }catch (SignatureVerificationException exception){ exception.printStackTrace(); apiResponse = ApiResponse.failed("无效签名",null, ResponseCode.UNAUTHORIZED.getCode()); } catch (TokenExpiredException exception){ exception.printStackTrace(); apiResponse = ApiResponse.failed("token过期",null, ResponseCode.UNAUTHORIZED.getCode()); } catch (AlgorithmMismatchException exception){ exception.printStackTrace(); apiResponse = ApiResponse.failed("token签名算法不一致",null, ResponseCode.UNAUTHORIZED.getCode());; } catch (Exception exception){ exception.printStackTrace(); apiResponse = ApiResponse.failed("token无效",null, ResponseCode.UNAUTHORIZED.getCode()); } if (Objects.isNull(apiResponse)) { filterChain.doFilter(request,response); } else { response.setStatus(200); response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); response.getWriter().print(JSON.toJSONString(apiResponse)); } } }
Springboot 配置
-
pom引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
-
创建配置文件
package com.smile.blog.config; import com.smile.blog.filter.JwtAuthenticationTokenFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.annotation.Resource; /** * @Notes * @Date 2022/3/17 * @Time 16:53 * @Author smile */ @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { private final String[] PATTERNS = { "/article/details" }; @Resource private AccessDeniedHandler AccessDeniedHandleImpl; @Resource private AuthenticationEntryPoint AuthenticationEntryPointImpl; @Resource private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; /*** * @Notes 定义加密规则 * * @return org.springframework.security.crypto.password.PasswordEncoder * @author smile * @date 2022/3/17 * @time 16:59 **/ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/auth/login").anonymous() .antMatchers(PATTERNS).permitAll() .anyRequest().authenticated(); //配置异常处理 http.exceptionHandling() .authenticationEntryPoint(AuthenticationEntryPointImpl) .accessDeniedHandler(AccessDeniedHandleImpl); //添加过滤器 http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); //跨域 http.cors(); } }
-
创建认证异常实现类
package com.smile.blog.handler; import com.alibaba.fastjson.JSON; import com.smile.blog.utils.http.HttpResponse; import com.smile.blog.utils.response.ApiResponse; import com.smile.blog.utils.response.ResponseCode; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @Notes 认证失败 * @Date 2022/3/19 * @Time 11:11 * @Author smile */ @Component public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { ApiResponse<Object> result = ApiResponse.failed(authException.getMessage(),null, ResponseCode.UNAUTHORIZED.getCode()); String json = JSON.toJSONString(result); HttpResponse.response(response,json); } }
-
创建权限异常实现类
package com.smile.blog.handler; import com.alibaba.fastjson.JSON; import com.smile.blog.utils.http.HttpResponse; import com.smile.blog.utils.response.ApiResponse; import com.smile.blog.utils.response.ResponseCode; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @Notes * @Date 2022/3/19 * @Time 11:22 * @Author smile */ @Component public class AccessDeniedHandleImpl implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { ApiResponse<Object> result = ApiResponse.failed("权限不足",null, ResponseCode.FORBIDDEN.getCode()); String json = JSON.toJSONString(result); HttpResponse.response(response,json); } }
-
创建User登录类
package com.smile.blog.domain; import lombok.Data; import com.smile.blog.entity.User; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; /** * @Notes * @Date 2022/3/18 * @Time 17:29 * @Author smile */ @Data @NoArgsConstructor @AllArgsConstructor public class UserLogin implements UserDetails { private User user; @Override public Collection<? extends GrantedAuthority> getAuthorities() { return null; } @Override public String getPassword() { return user.getPassword(); } @Override public String getUsername() { return user.getUsername(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }