怎样上传网站到空间,江苏建设是国企吗,网站域名变更怎么查询,英文网站建设模板下载文章目录 概要整体架构流程实现流程1、编写各种Handler2 、AccessToken处理器3、定义AuthenticationFilter 继承 OncePerRequestFilter #xff08;OncePerRequestFilter是Spring提供的一个过滤器基类#xff0c;它确保了在一次完整的HTTP请求中#xff0c;无论请求经过多少… 文章目录 概要整体架构流程实现流程1、编写各种Handler2 、AccessToken处理器3、定义AuthenticationFilter 继承 OncePerRequestFilter OncePerRequestFilter是Spring提供的一个过滤器基类它确保了在一次完整的HTTP请求中无论请求经过多少次内部转发过滤器的逻辑都只会被执行一次。这对于需要在请求处理之前或之后进行一次性设置或清理资源的场景特别有用。4、编写SecurityAutoConfiguration 把Handler和AccessTokenManager 注册成bean5、编写 WebSecurityAutoConfiguration 注册SecurityFilterChain的bean6 辅助类6.1 公共配置注册(如何不在采用的地方用EnableConfigurationProperties注解可以写在公共配置文件里面)6.2忽略url写在配置文件6.3 自定义UserDetailsServiceImpl实现UserDetailsService6.4 自定义redis操作6.5 自定义加密解密依据之前对接过微信支付相关token逻辑进行简单的RSA相关加解密 小结 概要
security-spring-boot-starter SpringSecurity参考笔记
整体架构流程 模块代码截图
实现流程
1、编写各种Handler
1.1 AccessDeniedHandler 处理当访问被拒绝时的逻辑
import com.core.web.Web;
import com.core.web.result.Result;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class myAccessDeniedHandler implements AccessDeniedHandler {Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {ResultObject result Result.fail();if (accessDeniedException ! null) {result.setMessage(accessDeniedException.getLocalizedMessage());}Web.Response.json(response, HttpStatus.FORBIDDEN, result);}
}1.2 AuthenticationEntryPoint 处理未认证逻辑
import com.core.web.Web;
import com.core.web.result.Result;
import com.core.web.result.ResultCode;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class myAuthenticationEntryPoint implements AuthenticationEntryPoint {Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {ResultObject result Result.build(ResultCode.UNAUTHORIZED);if (authException ! null !(authException instanceof InsufficientAuthenticationException)) {result.setMessage(authException.getLocalizedMessage());}Web.Response.json(response, HttpStatus.UNAUTHORIZED, result);}
}1.3 AuthenticationFailureHandler 处理认证失败逻辑
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class myAuthenticationFailureHandler implements AuthenticationFailureHandler {Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)throws IOException, ServletException {Web.Response.json(response, Result.fail(exception.getLocalizedMessage()));}
}1.4 AuthenticationSuccessHandler 处理认证成功逻辑
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class myAuthenticationSuccessHandler implements AuthenticationSuccessHandler {Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throws IOException, ServletException {LoginUser user (LoginUser) authentication.getPrincipal();AccessTokenManager.create(user);Web.Response.json(response, Result.ok(user));}
}1.5 LogoutSuccessHandler 处理退出登录逻辑 为了安全起见采用RES对token进行加密后端拿到数据后进行解密再做进一步的判断
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;Component
EnableConfigurationProperties(TokenProperties.class) // 如何不写这个注解可以采用写在第五步的 CommonConfig
public class JsonLogoutSuccessHandler implements LogoutSuccessHandler {Resourceprivate TokenProperties tokenProperties ;Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throws IOException, ServletException {// 获取请求参数数据InputStream inputStream request.getInputStream();//把inputStream 转mapObjectMapper mapper new ObjectMapper();// 前端采用post 请求/logout参数为key,value为token加密的密文的json数据MapString,String s mapper.readValue(inputStream, Map.class);// 解密得到tokenString token AesUtil.decryptToString(s.get(key));// 获取登录用户信息LoginUser user AccessTokenManager.getLoginUser(token);if($.isNotNull(user) !StringUtils.equals(tokenProperties.getScreen(), token)){AccessTokenManager.remove(token);}Web.Response.json(response, Result.ok());}
} 2 、AccessToken处理器
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.InitializingBean;import static com.zyc.core.Constants.Separator.COLON;RequiredArgsConstructor
public class AccessTokenManager implements InitializingBean {private static AccessTokenManager MANAGER;public static AccessTokenManager getInstance() {return MANAGER;}/*** 过期时间单位秒*/private static final long EXPIRE_IN_SECONDS 24 * 60 * 60;/*** 访问凭证缓存键*/public static final String TOKEN_CACHE_KEY token_to_user COLON;/*** 根据访问凭证获取登录用户信息** param accessToken 访问凭证* param T 用户信息类型* return 登录用户信息*/public static T extends LoginUser T getLoginUser(String accessToken) {T user RedisCache.get(getInstance().getCacheKey(accessToken));if (user null) {return null;}refresh(accessToken, user);return user;}public static void remove(String accessToken) {RedisCache.del(getInstance().getCacheKey(accessToken));}public static String create(LoginUser user) {String token $.id();user.setToken(token);refresh(token, user);return token;}public static void refresh(String accessToken, LoginUser user) {if ($.isBlank(accessToken)) {return;}boolean isSuperAdmin SecureContextHolder.hasSuperAdmin(user.getPermissions());if (isSuperAdmin) {RedisCache.set(getInstance().getCacheKey(accessToken), user);} else {RedisCache.set(getInstance().getCacheKey(accessToken), user, EXPIRE_IN_SECONDS);}}String getCacheKey(String accessToken) {return TOKEN_CACHE_KEY.concat(accessToken);}Overridepublic void afterPropertiesSet() throws Exception {MANAGER this;}
}3、定义AuthenticationFilter 继承 OncePerRequestFilter OncePerRequestFilter是Spring提供的一个过滤器基类它确保了在一次完整的HTTP请求中无论请求经过多少次内部转发过滤器的逻辑都只会被执行一次。这对于需要在请求处理之前或之后进行一次性设置或清理资源的场景特别有用。
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;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.List;
import java.util.Optional;
import java.util.stream.Collectors;
/*** 认证过滤* p* 用于从请求信息 {link HttpServletRequest} 获取访问凭证获取登录信息设置到安全认证上下文中* 以实现登录* /p* p* set before at {link org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter}* /p**/
Slf4j
public class AuthenticationFilter extends OncePerRequestFilter {Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException {log.debug([auth.filter] server_name: {} uri: {}, query: {},request.getServerName(), request.getRequestURI(), request.getQueryString());Authentication authentication getAuthentication(request);SecurityContextHolder.getContext().setAuthentication(authentication);Optional.ofNullable(authentication).ifPresent(auth - {ListString authorities auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());ContextHolder.set(SUPER_ADMIN, SecureContextHolder.hasSuperAdmin(authorities));});//TODO 对参数进行一些过滤校验/*ParameterRequestWrapper paramRequest new ParameterRequestWrapper(request);chain.doFilter(paramRequest, response);*/chain.doFilter(request, response);}/*** 获取认证信息** param request 请求信息* return 认证信息*/private Authentication getAuthentication(HttpServletRequest request) {String accessToken obtainAccessToken(request);log.debug([auth.filter] obtain access_token: {}, accessToken);if ($.isBlank(accessToken)) {return null;}LoginUser login AccessTokenManager.getLoginUser(accessToken);return Optional.ofNullable(login).map(user - new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities())).orElse(null);}/*** 获取访问凭证** param request 请求信息* return 访问凭证*/private String obtainAccessToken(HttpServletRequest request) {String token request.getHeader(TOKEN_HEAD);return Optional.ofNullable(token).orElseGet(() - request.getParameter(TOKEN_PARAM));}
}4、编写SecurityAutoConfiguration 把Handler和AccessTokenManager 注册成bean
import com.security.servlet.AccessTokenManager;
import com.security.servlet.handler.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
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.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;EnableConfigurationProperties(SecurityProperties.class) // 如何不写这个注解可以采用写在第五步的 CommonConfig
Configuration(proxyBeanMethods false)
Import(WebSecurityAutoConfiguration.class)
public class SecurityAutoConfiguration {BeanConditionalOnMissingBeanpublic AccessTokenManager accessTokenManager() {return new AccessTokenManager();}BeanConditionalOnMissingBeanpublic AuthenticationEntryPoint authenticationEntryPoint() {return new JsonAuthenticationEntryPoint();}BeanConditionalOnMissingBeanpublic AccessDeniedHandler accessDeniedHandler() {return new JsonAccessDeniedHandler();}BeanConditionalOnMissingBeanpublic AuthenticationFailureHandler authenticationFailureHandler() {return new JsonAuthenticationFailureHandler();}BeanConditionalOnMissingBeanpublic AuthenticationSuccessHandler authenticationSuccessHandler() {return new JsonAuthenticationSuccessHandler();}BeanConditionalOnMissingBeanpublic PasswordEncoder passwordEncoder() {return PasswordEncoderFactories.createDelegatingPasswordEncoder();}BeanConditionalOnMissingBeanpublic LogoutSuccessHandler logoutSuccessHandler() {return new JsonLogoutSuccessHandler();}
}
5、编写 WebSecurityAutoConfiguration 注册SecurityFilterChain的bean
import com.security.configurers.AuthorizeRequestsCustomizer;
import com.security.servlet.filter.AuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;ConditionalOnWebApplication(type ConditionalOnWebApplication.Type.SERVLET
)
Configuration(proxyBeanMethods false)
RequiredArgsConstructor
public class WebSecurityAutoConfiguration {/*** 默认静态资源常量数组*/private static final String[] DEFAULT_STATIC_RESOURCES new String[]{/favicon.ico,/**/*.css,/**/*.js,/doc.html,/swagger-ui/**,/swagger-ui.html,/swagger-ui/index.html,/swagger-resources/**,/v3/api-docs,/v3/api-docs/**};private final SecurityProperties securityProperties;private final AuthenticationSuccessHandler authenticationSuccessHandler;private final AuthenticationFailureHandler authenticationFailureHandler;private final AuthenticationEntryPoint authenticationEntryPoint;private final AccessDeniedHandler accessDeniedHandler;private final LogoutSuccessHandler loggingSuccessHandler;private final ListAuthorizeRequestsCustomizer authorizeRequestsCustomizers;Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.formLogin(form - form.successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler))// CSRF 禁用因为不使用 Session.csrf(AbstractHttpConfigurer::disable).sessionManagement(sessionManagement -sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))// 异常处理.exceptionHandling(exceptionHandling -exceptionHandling.accessDeniedHandler(accessDeniedHandler).authenticationEntryPoint(authenticationEntryPoint))// 忽略认证.authorizeRequests(auth - auth.antMatchers(DEFAULT_STATIC_RESOURCES).permitAll().antMatchers($.toArray(securityProperties.getIgnoreUrls())).permitAll())// 兜底必须通过认证才能访问.authorizeRequests().anyRequest().authenticated().and()// 前置通过凭证获取登录信息.addFilterBefore(new AuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)//退出逻辑.logout().logoutSuccessHandler(loggingSuccessHandler);return http.build();}AntPathRequestMatcher[] convertRequestMatcher(StreamString stream) {return stream.map(AntPathRequestMatcher::new).collect(Collectors.toList()).toArray(new AntPathRequestMatcher[]{});}
}6 辅助类
6.1 公共配置注册(如何不在采用的地方用EnableConfigurationProperties注解可以写在公共配置文件里面)
import com..autoconfigure.ConfigProperties;
import com.boot.autoconfigure.security.TokenProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;EnableConfigurationProperties({SecurityProperties.class,TokenProperties.class
})
Configuration
public class CommonConfig {
}6.2忽略url写在配置文件
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;import java.util.ArrayList;
import java.util.List;Data
ConfigurationProperties(cfg.security)
public class SecurityProperties {/*** 忽略 url*/private ListString ignoreUrls new ArrayList();
}特定token配置在配置文件
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
Data
ConfigurationProperties(prefix ems.token)
public class TokenProperties {private String screen;
}自定义LoginUser 继承UserDetails
import cn.hutool.core.map.MapUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;import java.time.LocalDate;
import java.util.Collection;
import java.util.Map;
import java.util.Set;Data
Accessors(chain true)
public class LoginUser implements UserDetails, CredentialsContainer {/*** 主键标识*/private String id;/*** 用户名*/private String username;/*** 密码*/private String password;/*** 昵称*/private String nickname;/*** 权限集合*/private SetString permissions;/*** 访问凭证*/private String token;/*** 扩展信息*/private MapString, Object extra;/*** 上下文信息*/private MapString, Object context;/*** 机构标识*/private String orgId;/*** 机构类型*/private Integer orgType;/*** 机构名称*/private String orgName;/*** 有效期*/private LocalDate validityPeriod;JsonIgnoreOverridepublic Collection? extends GrantedAuthority getAuthorities() {return AuthorityUtils.createAuthorityList($.toArray(permissions, String.class));}JsonIgnoreOverridepublic String getPassword() {return password;}JsonIgnoreOverridepublic boolean isAccountNonExpired() {return true;}JsonIgnoreOverridepublic boolean isAccountNonLocked() {return true;}JsonIgnoreOverridepublic boolean isCredentialsNonExpired() {return true;}JsonIgnoreOverridepublic boolean isEnabled() {return true;}Overridepublic void eraseCredentials() {this.password null;}
}6.3 自定义UserDetailsServiceImpl实现UserDetailsService
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.time.LocalDate;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;Service
RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {private final OperatorService operatorService;private final RoleService roleService;private final MenuService menuService;private final ProjectService projectService;private final OrgService orgService;Overridepublic UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {Operator operator operatorService.lambdaQuery().eq(Operator::getUsername, username).oneOpt().orElseThrow(() - new UsernameNotFoundException(用户名或者密码错误));ListRole roles roleService.listByOperator(operator.getId(), operator.getOrgId());boolean isSuperAdmin roles.stream().anyMatch(role - $.equals(role.getId(), Constants.Default.SUPER_ADMIN));SetString roleIds roles.stream().map(Role::getId).collect(Collectors.toSet());// 菜单权限SetString permissions menuService.listByRole(isSuperAdmin, $.toArray(roleIds, String.class)).stream().map(Menu::getPermission).filter(Kit::isNotBlank).collect(Collectors.toSet());permissions.addAll(roleIds.stream().map(Constants.Default.ROLE_PREFIX::concat).collect(Collectors.toList()));// 项目权限SetString projectIds projectService.listByRole(operator.getOrgId(), isSuperAdmin, roles);permissions.addAll(projectIds.stream().filter(Kit::isNotBlank).map(Values.PROJECT_PREFIX::concat).collect(Collectors.toList()));String password Constants.Security.DEFAULT_ENCRYPTION_SIGNATURE.concat(operator.getPassword());Org org orgService.getById(operator.getOrgId());//如果机构设置了有效期则有效期过后不能登录LocalDate now LocalDate.now();if ($.isNotNull(org.getValidityPeriod())) {if (now.isAfter(org.getValidityPeriod())) {throw new AccountExpiredException(账户过期请联系管理员);}}LoginUser user new LoginUser().setUsername(username).setPassword(password).setPermissions(permissions);user.setId(operator.getId());user.setNickname(operator.getNickname());user.setOrgId(operator.getOrgId());user.setOrgType(org.getOrgType());user.setOrgName(org.getOrgName());user.setValidityPeriod(org.getValidityPeriod());return user;}}6.4 自定义redis操作
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.*;import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;SuppressWarnings(unchecked)
Slf4j
public class RedisCache {private static RedisCache redisCache;private final RedisTemplateString, Object redisTemplate;private final ValueOperationsString, Object valueOperations;private final HashOperationsString, String, Object hashOperations;private final ListOperationsString, Object listOperations;private final SetOperationsString, Object setOperations;private final ZSetOperationsString, Object zSetOperations;private final String keyPrefix;public RedisCache(RedisTemplateString, Object redisTemplate, String keyPrefix) {this.redisTemplate redisTemplate;this.keyPrefix keyPrefix;this.valueOperations redisTemplate.opsForValue();this.hashOperations redisTemplate.opsForHash();this.listOperations redisTemplate.opsForList();this.setOperations redisTemplate.opsForSet();this.zSetOperations redisTemplate.opsForZSet();redisCache this;}/*** 获取缓存** param key 键* param T 类型* return 指定类型值*/public static T T get(String key) {return key null ? null : (T) opsValue().get(obtainKey(key));}/*** 写入缓存** param key 键* param value 值* return true成功*/public static boolean set(String key, Object value) {try {opsValue().set(obtainKey(key), value);return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** 写入缓存并设置过期时间** param key 键* param value 值* param second 过期时间单位秒* return true成功*/public static boolean set(String key, Object value, long second) {try {if (second 0) {opsValue().set(obtainKey(key), value, second, TimeUnit.SECONDS);} else {set(obtainKey(key), value);}return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** 写入缓存并设置过期时间** param key 键* param value 值* param time 过期时间* param unit 时间单位* return true成功*/public static boolean set(String key, Object value, long time, TimeUnit unit) {try {if (time 0) {opsValue().set(obtainKey(key), value, time, unit);} else {set(obtainKey(key), value);}return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** 设置指定缓存的失效时间** param key 键* param second 过期时间单位秒* return true成功*/public static boolean expire(String key, long second) {try {if (second 0) {template().expire(obtainKey(key), second, TimeUnit.SECONDS);}return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** 获取指定缓存的过期时间** param key 键* return 过期时间0代表永久有效*/public static long getExpire(String key) {return Optional.ofNullable(template().getExpire(obtainKey(key), TimeUnit.SECONDS)).orElse(0L);}/*** 判断缓存是否存在** param key 键* return true存在*/public static boolean has(String key) {try {return Optional.ofNullable(template().hasKey(obtainKey(key))).orElse(false);} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** 删除缓存** param key 键支持多个*/public static void del(String... key) {if (key ! null key.length 0) {if (key.length 1) {template().delete(obtainKey(key[0]));} else {template().delete(Arrays.stream(key).map(RedisCache::obtainKey).collect(Collectors.toList()));}}}/*** 递增指定数值** param key 键* param delta 递增数值大于0* return 递增后的数值*/public static long incr(String key, long delta) {if (delta 0) {throw new RuntimeException(递增数值必须大于 0);}return Optional.ofNullable(opsValue().increment(obtainKey(key), delta)).orElse(0L);}/*** 递减指定数值** param key 键* param delta 递减数值大于0* return 递减后的数值*/public static long decr(String key, long delta) {if (delta 0) {throw new RuntimeException(递减数值必须大于 0);}return Optional.ofNullable(opsValue().decrement(obtainKey(key), delta)).orElse(0L);}/*** Hash* 获取指定字段的值** param key 键* param field 字段* param T 类型* return 指定类型值*/public static T T hget(String key, String field) {return (T) opsHash().get(obtainKey(key), field);}/*** Hash* 设置指定键字段值** param key 键* param field 字段* param value 值* return true成功*/public static boolean hset(String key, String field, Object value) {try {opsHash().put(obtainKey(key), field, value);return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** Hash* 设置指定键字段值** param key 键* param field 字段* param value 值* param second 过期时间单位秒* return true成功*/public static boolean hset(String key, String field, Object value, long second) {try {opsHash().put(obtainKey(key), field, value);if (second 0) {expire(obtainKey(key), second);}return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** Hash* 获取所有的键值** param key 键* return 所有的键值*/public static T MapString, T hgetall(String key) {return (MapString, T) opsHash().entries(obtainKey(key));}/*** Hash* 设置多个字段值** param key 键* param map 多个字段值* return true成功*/public static T boolean hmset(String key, MapString, T map) {try {opsHash().putAll(obtainKey(key), map);return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** Hash* 设置多个字段值并设置过期时间** param key 键* param map 多个字段值* param second 过期时间单位秒* return true成功*/public static T boolean hmset(String key, MapString, T map, long second) {try {opsHash().putAll(obtainKey(key), map);if (second 0) {expire(obtainKey(key), second);}return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** Hash* 删除指定键指定字段缓存** param key 键* param fields 字段支持多个*/public static void hdel(String key, Object... fields) {opsHash().delete(obtainKey(key), fields);}/*** Hash* 判断指定字段是否存在** param key 键* param field 字段* return true成功*/public static boolean hhas(String key, String field) {return opsHash().hasKey(obtainKey(key), field);}/*** Hash* 递增指定字段数值** param key 键* param field 字段* param delta 递增数值* return 递增后的数值*/public static long hincr(String key, String field, long delta) {return opsHash().increment(obtainKey(key), field, delta);}/*** Hash* 递减指定字段数值** param key 键* param field 字段* param delta 递减数值* return 递减后的数值*/public static long hdecr(String key, String field, long delta) {return opsHash().increment(obtainKey(key), field, -delta);}/*** Set* 添加元素** param key 键* param values 值支持多个* return 成功个数*/public static long sadd(String key, Object... values) {try {return Optional.ofNullable(opsSet().add(obtainKey(key), values)).orElse(0L);} catch (Exception e) {log.error(e.getMessage(), e);return 0L;}}/*** Set* 添加元素** param key 键* param second 过期时间单位秒* param values 值支持多个* return 成功个数*/public static long sadd(String key, long second, Object... values) {try {Long count opsSet().add(obtainKey(key), values);if (second 0) {expire(obtainKey(key), second);}return Optional.ofNullable(count).orElse(0L);} catch (Exception e) {log.error(e.getMessage(), e);return 0;}}/*** Set* 获取缓存大小** param key 键* return 大小*/public static long scard(String key) {try {return Optional.ofNullable(opsSet().size(obtainKey(key))).orElse(0L);} catch (Exception e) {log.error(e.getMessage(), e);return 0;}}/*** Set* 移除元素** param key 键* param values 值支持多个* return 移除个数*/public static long srem(String key, Object... values) {try {return Optional.ofNullable(opsSet().remove(obtainKey(key), values)).orElse(0L);} catch (Exception e) {log.error(e.getMessage(), e);return 0;}}/*** List* 列表头部插入缓存** param key 键* param value 值* return true成功*/public static boolean lpush(String key, Object value) {try {opsList().leftPush(obtainKey(key), value);return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** List* 列表头部插入多个缓存** param key 键* param second 过期时间单位秒* param values 值支持多个* return true成功*/public static boolean lpush(String key, long second, Object... values) {try {opsList().leftPushAll(obtainKey(key), values);if (second 0) {expire(obtainKey(key), second);}return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** List* 列表尾部插入缓存** param key 键* param value 值* return true成功*/public static boolean lrpush(String key, Object value) {try {opsList().rightPush(obtainKey(key), value);return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** List* 列表尾部插入多个缓存** param key 键* param second 过期时间单位秒* param values 值支持多个* return true成功*/public static boolean lrpush(String key, long second, Object... values) {try {opsList().rightPushAll(obtainKey(key), values);if (second 0) {expire(obtainKey(key), second);}return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** List* 设置指定索引的值** param key 键* param index 索引* param value 值* return true成功*/public static boolean lset(String key, long index, Object value) {try {opsList().set(obtainKey(key), index, value);return true;} catch (Exception e) {log.error(e.getMessage(), e);return false;}}/*** List* 获取指定范围内的元素** param key 键* param start 开始索引* param end 结束索引* param T 类型* return 元素列表*/public static T ListT lrange(String key, long start, long end) {try {return (ListT) opsList().range(obtainKey(key), start, end);} catch (Exception e) {log.error(e.getMessage(), e);return null;}}/*** List* 获取指定列表缓存的长度** param key 键* return 长度*/public static long llen(String key) {try {return Optional.ofNullable(opsList().size(obtainKey(key))).orElse(0L);} catch (Exception e) {log.error(e.getMessage(), e);return 0;}}/*** List* 获取指定索引对应的值** param key 键* param index 索引* param T 类型* return 值*/public static T T lindex(String key, long index) {try {return (T) opsList().index(obtainKey(key), index);} catch (Exception e) {log.error(e.getMessage(), e);return null;}}/*** List* 移动指定个数的元素** param key 键* param count 移除个数* param value 值* return 成功移除个数*/public static long lrem(String key, long count, Object value) {try {return Optional.ofNullable(opsList().remove(obtainKey(key), count, value)).orElse(0L);} catch (Exception e) {log.error(e.getMessage(), e);return 0;}}private static String obtainKey(String key) {return Optional.ofNullable(redisCache.keyPrefix).map(prefix - prefix key).orElse(key);}public static RedisTemplateString, Object template() {return redisCache.redisTemplate;}public static ValueOperationsString, Object opsValue() {return redisCache.valueOperations;}public static HashOperationsString, String, Object opsHash() {return redisCache.hashOperations;}public static ListOperationsString, Object opsList() {return redisCache.listOperations;}public static SetOperationsString, Object opsSet() {return redisCache.setOperations;}SuppressWarnings({AlibabaLowerCamelCaseVariableNaming})public static ZSetOperationsString, Object opsZSet() {return redisCache.zSetOperations;}public static GeoOperationsString, Object opsGeo() {return template().opsForGeo();}public static StreamOperationsString, Object, Object opsStream() {return template().opsForStream();}public static ClusterOperationsString, Object opsCluster() {return template().opsForCluster();}
}6.5 自定义加密解密依据之前对接过微信支付相关token逻辑进行简单的RSA相关加解密
package com.zyc.security.servlet.handler;//import com.ahlinksoft.common.utils.SysPropUtils;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
Component
Slf4j
public class AesUtil {static final int KEY_LENGTH_BYTE 32;static final int TAG_LENGTH_BIT 128;private final static String publicKey MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC69/jlQYoDKIWLR9dGD0/LLInDKZyptdrdeqPQY9lBRmgcR2DHvyEDOe6cbGvV0HcfOef6FFEqW2dzadjglbBqPMQttb50kEn4bZTj2mMvQex51tD7AgmbEvV5XFi9DBYtxaM8c3DhBIgobF3zzybqj3T9qY6ZPzAaQmKywIDAQAB;private final static String privateKey MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALr3OVBigMohYtH10YPT8ssicP4pnKm12t16o9Bj2UFGaBxHYMe/IQM57pxsa9X7Qdx855/oUUSpbZ3Np2OCVsGo8xC21vn7SQSfhtlP6PaYy9B7HnW0PsCCZsS9XlcWL0MFi3FozxzcOEEj6ChsXfPPJuqPdP2pjpk/MBpCYrLAgMBAAECgYBFQlhz7FxIoTkfCCTJsiBX3g7GhpR6Ai3og8y49os826/LjDtneBIIhJNOsJEmqAaI7IBXZWYDJU43klr65Kw/z0h81jCFNOxyBmSkweWRXGYl77BxmTtxvvDrEEcj3z2e/plzeOwJpncErqwPgXz60zpuXmkNvtm5YnKjIp0QJBAPaGU4ZpQjWbdjE9fSEkXYI3tReNpsGLuGbaExw4P5v1iaSuSIwhz0oorRMDWvXijAEEkDKYGyV8B8s9w/F8okCQQDCJ6VAe3MBln/wCxMI2ksnEDfViFLzHljzrw4QWuq4pFkM0LmjqBAOh4SuGtnSAATgDn3cBcrW61lXY7d0A2zAkAH2qkIvzeUiCuRrLe4UfKPc0EOdHM1Rksn35YDFmnqQMAyF8lXctPa6F9I1pWBZt0d9mPUJmf0BvPdeBQSVBAkAUg/XtO14qo8l/BtyLCe35Abi0ooQJVoKVtUCqL8Evo4YZWZDUHzUbIy8LPApRYEeFw/riN0nGpVFK6893gLAkA0VQEWHjzeq0qCJL8F9UXW67zfT/J3hMlahK0YXxfdU9kusqMjvHxzLg6iZX/jaK1T3kWj2EafwUSxhJf1b7X;private static MapString, String params new HashMap();//私钥解密public static byte[] decrypt(byte[] content, PrivateKey privateKey) throws Exception{Cipher cipherCipher.getInstance(RSA);cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(content);}//私钥解密public static String decryptToString(String ciphertext) {try {Cipher cipher Cipher.getInstance(RSA);cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));byte[ ] content Base64.getDecoder().decode(ciphertext);byte[ ] doFinalResult null;try {doFinalResult cipher.doFinal(content);} catch (IllegalBlockSizeException e) {throw new RuntimeException(e);} catch (BadPaddingException e) {throw new RuntimeException(e);}try {return new String(doFinalResult, utf-8);} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {throw new IllegalStateException(e);} catch (InvalidKeyException e) {throw new IllegalArgumentException(e);}}//将base64编码后的公钥字符串转成PublicKey实例public static PublicKey getPublicKey(String publicKey) throws Exception{byte[ ] keyBytesBase64.getDecoder().decode(publicKey.getBytes());X509EncodedKeySpec keySpecnew X509EncodedKeySpec(keyBytes);KeyFactory keyFactoryKeyFactory.getInstance(RSA);return keyFactory.generatePublic(keySpec);}/*** String转私钥PrivateKey* param key* return* throws Exception*/public static PrivateKey getPrivateKey(String key) {byte[] keyBytes;try {keyBytes (new BASE64Decoder()).decodeBuffer(key);} catch (IOException e) {throw new RuntimeException(e);}PKCS8EncodedKeySpec keySpec new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory null;try {keyFactory KeyFactory.getInstance(RSA);} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}PrivateKey privateKey null;try {privateKey keyFactory.generatePrivate(keySpec);} catch (InvalidKeySpecException e) {throw new RuntimeException(e);}return privateKey;}//生成密钥对public static KeyPair genKeyPair(int keyLength) throws Exception{KeyPairGenerator keyPairGeneratorKeyPairGenerator.getInstance(RSA);keyPairGenerator.initialize(1024);return keyPairGenerator.generateKeyPair();}/*** 获取私钥。** param filename 私钥文件路径 (required)* return 私钥对象*//*public static PrivateKey getPrivateKey(String filename) throws IOException {String content new String(Files.readAllBytes(Paths.get(filename)), utf-8);try {String privateKey content.replace(-----BEGIN PRIVATE KEY-----, ).replace(-----END PRIVATE KEY-----, ).replaceAll(\\s, );KeyFactory kf KeyFactory.getInstance(RSA);return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));} catch (NoSuchAlgorithmException e) {throw new RuntimeException(当前Java环境不支持RSA, e);} catch (InvalidKeySpecException e) {throw new RuntimeException(无效的密钥格式);}}*/public static void main(String[] args) throws Exception {String data028fbb4b16bf48bf93a02d1d0687e149;/*KeyPair keyPairgenKeyPair(1024);//获取公钥并以base64格式打印出来PublicKey publicKeykeyPair.getPublic();System.out.println(公钥new String(Base64.getEncoder().encode(publicKey.getEncoded())));//获取私钥并以base64格式打印出来PrivateKey privateKeykeyPair.getPrivate();System.out.println(私钥new String(Base64.getEncoder().encode(privateKey.getEncoded())));*///公钥加密byte[] encryptedBytesencrypt(data.getBytes(), getPublicKey(publicKey));log.debug(加密后{},encryptToString(encryptedBytes));//私钥解密byte[] decryptedBytesdecrypt(encryptedBytes, getPrivateKey(privateKey));log.debug(解密后{},new String(decryptedBytes,utf-8));//私钥解密String decryptedString decryptToString(encryptToString(encryptedBytes));log.debug(解密后{},decryptedString);}//公钥加密public static byte[] encrypt(byte[] content, PublicKey publicKey) throws Exception{Cipher cipherCipher.getInstance(RSA);//java默认RSARSA/ECB/PKCS1Paddingcipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(content);}public static String encryptToString(byte[] encryptedBytes) throws Exception{return Base64.getEncoder().encodeToString(encryptedBytes);}}小结 提示这里可以添加总结 文章转载自: http://www.morning.zbkdm.cn.gov.cn.zbkdm.cn http://www.morning.hjrjr.cn.gov.cn.hjrjr.cn http://www.morning.jfwrf.cn.gov.cn.jfwrf.cn http://www.morning.pmsl.cn.gov.cn.pmsl.cn http://www.morning.wtwhj.cn.gov.cn.wtwhj.cn http://www.morning.gskzy.cn.gov.cn.gskzy.cn http://www.morning.mqgqf.cn.gov.cn.mqgqf.cn http://www.morning.rqsnl.cn.gov.cn.rqsnl.cn http://www.morning.pngfx.cn.gov.cn.pngfx.cn http://www.morning.lsmnn.cn.gov.cn.lsmnn.cn http://www.morning.dpdr.cn.gov.cn.dpdr.cn http://www.morning.dbcw.cn.gov.cn.dbcw.cn http://www.morning.jlnlr.cn.gov.cn.jlnlr.cn http://www.morning.crtgd.cn.gov.cn.crtgd.cn http://www.morning.qrpdk.cn.gov.cn.qrpdk.cn http://www.morning.kltsn.cn.gov.cn.kltsn.cn http://www.morning.cdlewan.com.gov.cn.cdlewan.com http://www.morning.kcbml.cn.gov.cn.kcbml.cn http://www.morning.mqxzh.cn.gov.cn.mqxzh.cn http://www.morning.dfqmy.cn.gov.cn.dfqmy.cn http://www.morning.hjbrd.cn.gov.cn.hjbrd.cn http://www.morning.tlfyb.cn.gov.cn.tlfyb.cn http://www.morning.pakistantractors.com.gov.cn.pakistantractors.com http://www.morning.pmrlt.cn.gov.cn.pmrlt.cn http://www.morning.twdwy.cn.gov.cn.twdwy.cn http://www.morning.nqfxq.cn.gov.cn.nqfxq.cn http://www.morning.rwjfs.cn.gov.cn.rwjfs.cn http://www.morning.jjzrh.cn.gov.cn.jjzrh.cn http://www.morning.gyylt.cn.gov.cn.gyylt.cn http://www.morning.lwzpp.cn.gov.cn.lwzpp.cn http://www.morning.prznc.cn.gov.cn.prznc.cn http://www.morning.gmgyt.cn.gov.cn.gmgyt.cn http://www.morning.zwmjq.cn.gov.cn.zwmjq.cn http://www.morning.rlzxr.cn.gov.cn.rlzxr.cn http://www.morning.zffps.cn.gov.cn.zffps.cn http://www.morning.bsqkt.cn.gov.cn.bsqkt.cn http://www.morning.rgrz.cn.gov.cn.rgrz.cn http://www.morning.rdtp.cn.gov.cn.rdtp.cn http://www.morning.ylkkh.cn.gov.cn.ylkkh.cn http://www.morning.dmwbs.cn.gov.cn.dmwbs.cn http://www.morning.bzfld.cn.gov.cn.bzfld.cn http://www.morning.qgwpx.cn.gov.cn.qgwpx.cn http://www.morning.jcxzq.cn.gov.cn.jcxzq.cn http://www.morning.xnqjs.cn.gov.cn.xnqjs.cn http://www.morning.tlzbt.cn.gov.cn.tlzbt.cn http://www.morning.tnjz.cn.gov.cn.tnjz.cn http://www.morning.kqlrl.cn.gov.cn.kqlrl.cn http://www.morning.rjhts.cn.gov.cn.rjhts.cn http://www.morning.lxfyn.cn.gov.cn.lxfyn.cn http://www.morning.mdpkf.cn.gov.cn.mdpkf.cn http://www.morning.ppqjh.cn.gov.cn.ppqjh.cn http://www.morning.xqnzn.cn.gov.cn.xqnzn.cn http://www.morning.dygqq.cn.gov.cn.dygqq.cn http://www.morning.kxbry.cn.gov.cn.kxbry.cn http://www.morning.mrqwy.cn.gov.cn.mrqwy.cn http://www.morning.jwxnr.cn.gov.cn.jwxnr.cn http://www.morning.bgrsr.cn.gov.cn.bgrsr.cn http://www.morning.sfnr.cn.gov.cn.sfnr.cn http://www.morning.txqgd.cn.gov.cn.txqgd.cn http://www.morning.kdnbf.cn.gov.cn.kdnbf.cn http://www.morning.cnlmp.cn.gov.cn.cnlmp.cn http://www.morning.yrmpr.cn.gov.cn.yrmpr.cn http://www.morning.ghxtk.cn.gov.cn.ghxtk.cn http://www.morning.mxnhq.cn.gov.cn.mxnhq.cn http://www.morning.stph.cn.gov.cn.stph.cn http://www.morning.llxyf.cn.gov.cn.llxyf.cn http://www.morning.bzlfw.cn.gov.cn.bzlfw.cn http://www.morning.drzkk.cn.gov.cn.drzkk.cn http://www.morning.wfjrl.cn.gov.cn.wfjrl.cn http://www.morning.hrzky.cn.gov.cn.hrzky.cn http://www.morning.tkcz.cn.gov.cn.tkcz.cn http://www.morning.zwzwn.cn.gov.cn.zwzwn.cn http://www.morning.zpkfb.cn.gov.cn.zpkfb.cn http://www.morning.njnqn.cn.gov.cn.njnqn.cn http://www.morning.dnmwl.cn.gov.cn.dnmwl.cn http://www.morning.rylr.cn.gov.cn.rylr.cn http://www.morning.crhd.cn.gov.cn.crhd.cn http://www.morning.swimstaracademy.cn.gov.cn.swimstaracademy.cn http://www.morning.pwsnr.cn.gov.cn.pwsnr.cn http://www.morning.nzkkh.cn.gov.cn.nzkkh.cn