文章目录
- Java secret - 03
-
- 源管理工具类
- 全局邮件帐户
- 邮件内部工具类
- 邮件发送客户端
- 邮件账户对象
- 邮件异常工具类
- 邮件工具类
- 邮件用户名密码验证器
- Redis使用FastJson序列化
- redis配置
- 缓存 通用常量
- spring redis 工具类
- Token解析器
- Redis授权认证器
- Redis授权
- 文件上传工具类
Java secret - 03
源管理工具类
package com.xueyi.common.datasource.utils;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.exception.ServiceException;
import com.xueyi.common.core.exception.UtilException;
import com.xueyi.common.core.utils.core.CollUtil;
import com.xueyi.common.core.utils.core.ObjectUtil;
import com.xueyi.common.core.utils.core.SpringUtil;
import com.xueyi.common.core.utils.core.StrUtil;
import com.xueyi.tenant.api.source.domain.dto.TeSourceDto;
import lombok.extern.slf4j.Slf4j;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Slf4j
public class DSUtil {
public static String loadDs(String sourceName) {
if (StrUtil.isEmpty(sourceName)) {
throw new UtilException("数据源不存在!");
} else if (checkHasDs(sourceName)) {
return sourceName;
}
TeSourceDto source = SourceUtil.getTeSourceCache(sourceName);
if (ObjectUtil.isNull(source)) {
throw new UtilException("数据源缓存不存在!");
}
addDs(source);
return sourceName;
}
public static void addDs(TeSourceDto source) {
try {
DefaultDataSourceCreator dataSourceCreator = SpringUtil.getBean(DefaultDataSourceCreator.class);
DataSourceProperty dataSourceProperty = new DataSourceProperty();
dataSourceProperty.setDriverClassName(source.getDriverClassName());
dataSourceProperty.setUrl(source.getUrlPrepend() + source.getUrlAppend());
dataSourceProperty.setUsername(source.getUserName());
dataSourceProperty.setPassword(source.getPassword());
DataSource dataSource = SpringUtil.getBean(DataSource.class);
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(source.getSlave(), dataSource);
} catch (Exception e) {
log.error(e.getMessage());
throw new UtilException("数据源添加失败!");
}
}
public static void delDs(String slave) {
try {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) SpringUtil.getBean(DataSource.class);
ds.removeDataSource(slave);
} catch (Exception e) {
log.error(e.getMessage());
throw new UtilException("数据源删除失败!");
}
}
public static void getDs() {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) SpringUtil.getBean(DataSource.class);
ds.getDataSources().keySet().forEach(System.out::println);
}
public static boolean checkHasDs(String slave) {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) SpringUtil.getBean(DataSource.class);
return ds.getDataSources().containsKey(slave);
}
public static String getNowDsName() {
return DynamicDataSourceContextHolder.peek();
}
public static void testDs(TeSourceDto source) {
try {
Class.forName(source.getDriverClassName());
} catch (Exception e) {
log.error(e.getMessage());
throw new UtilException("数据源驱动加载失败,请检查驱动信息!");
}
try {
Connection dbConn = DriverManager.getConnection(source.getUrlPrepend() + source.getUrlAppend(), source.getUserName(), source.getPassword());
dbConn.close();
} catch (Exception e) {
log.error(e.getMessage());
throw new UtilException("数据源连接失败,请检查连接信息!");
}
}
public static void testSlaveDs(TeSourceDto source, List<String> needTable) {
try {
Class.forName(source.getDriverClassName());
} catch (Exception e) {
log.error(e.getMessage());
throw new ServiceException("数据源驱动加载失败");
}
try {
Connection dbConn = DriverManager.getConnection(source.getUrlPrepend() + source.getUrlAppend(), source.getUserName(), source.getPassword());
PreparedStatement statement = dbConn.prepareStatement("select table_name from information_schema.tables where table_schema = (select database())");
ResultSet resultSet = statement.executeQuery();
Set<String> tableNameList = new HashSet<>();
while (resultSet.next()) {
tableNameList.add(resultSet.getString("table_name"));
}
Set<String> slaveTables = new HashSet<>(needTable);
slaveTables.removeAll(tableNameList);
if (CollUtil.isNotEmpty(slaveTables)) {
throw new ServiceException("请连接包含子库数据表信息的数据源!");
}
dbConn.close();
} catch (Exception e) {
log.error(e.getMessage());
throw new ServiceException("数据源连接失败,请检查连接信息!");
}
}
}
全局邮件帐户
package com.xueyi.common.mail.utils;
import cn.hutool.core.io.IORuntimeException;
public enum GlobalMailAccount {
INSTANCE;
private final MailAccount mailAccount;
GlobalMailAccount() {
mailAccount = createDefaultAccount();
}
public MailAccount getAccount() {
return this.mailAccount;
}
private MailAccount createDefaultAccount() {
for (String mailSettingPath : MailAccount.MAIL_SETTING_PATHS) {
try {
return new MailAccount(mailSettingPath);
} catch (IORuntimeException ignore) {
}
}
return null;
}
}
邮件内部工具类
package com.xueyi.common.mail.utils;
import cn.hutool.core.util.ArrayUtil;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeUtility;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class InternalMailUtil {
public static InternetAddress[] parseAddressFromStrs(String[] addrStrs, Charset charset) {
final List<InternetAddress> resultList = new ArrayList<>(addrStrs.length);
InternetAddress[] addrs;
for (String addrStr : addrStrs) {
addrs = parseAddress(addrStr, charset);
if (ArrayUtil.isNotEmpty(addrs)) {
Collections.addAll(resultList, addrs);
}
}
return resultList.toArray(new InternetAddress[0]);
}
public static InternetAddress parseFirstAddress(String address, Charset charset) {
final InternetAddress[] internetAddresses = parseAddress(address, charset);
if (ArrayUtil.isEmpty(internetAddresses)) {
try {
return new InternetAddress(address);
} catch (AddressException e) {
throw new MailException(e);
}
}
return internetAddresses[0];
}
public static InternetAddress[] parseAddress(String address, Charset charset) {
InternetAddress[] addresses;
try {
addresses = InternetAddress.parse(address);
} catch (AddressException e) {
throw new MailException(e);
}
if (ArrayUtil.isNotEmpty(addresses)) {
final String charsetStr = null == charset ? null : charset.name();
for (InternetAddress internetAddress : addresses) {
try {
internetAddress.setPersonal(internetAddress.getPersonal(), charsetStr);
} catch (UnsupportedEncodingException e) {
throw new MailException(e);
}
}
}
return addresses;
}
public static String encodeText(String text, Charset charset) {
try {
return MimeUtility.encodeText(text, charset.name(), null);
} catch (UnsupportedEncodingException e) {
}
return text;
}
}
邮件发送客户端
package com.xueyi.common.mail.utils;
import cn.hutool.core.builder.Builder;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.activation.DataHandler;
import jakarta.activation.DataSource;
import jakarta.activation.FileDataSource;
import jakarta.activation.FileTypeMap;
import jakarta.mail.Address;
import jakarta.mail.MessagingException;
import jakarta.mail.Multipart;
import jakarta.mail.SendFailedException;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
import jakarta.mail.internet.MimeUtility;
import jakarta.mail.util.ByteArrayDataSource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.Serial;
import java.nio.charset.Charset;
import java.util.Date;
public class Mail implements Builder<MimeMessage> {
@Serial
private static final long serialVersionUID = 1L;
private final MailAccount mailAccount;
private String[] tos;
private String[] ccs;
private String[] bccs;
private String[] reply;
private String title;
private String content;
private boolean isHtml;
private final Multipart multipart = new MimeMultipart();
private boolean useGlobalSession = false;
private PrintStream debugOutput;
public static Mail create(MailAccount mailAccount) {
return new Mail(mailAccount);
}
public static Mail create() {
return new Mail();
}
public Mail() {
this(GlobalMailAccount.INSTANCE.getAccount());
}
public Mail(MailAccount mailAccount) {
mailAccount = (null != mailAccount) ? mailAccount : GlobalMailAccount.INSTANCE.getAccount();
this.mailAccount = mailAccount.defaultIfEmpty();
}
public Mail to(String... tos) {
return setTos(tos);
}
public Mail setTos(String... tos) {
this.tos = tos;
return this;
}
public Mail setCcs(String... ccs) {
this.ccs = ccs;
return this;
}
public Mail setBccs(String... bccs) {
this.bccs = bccs;
return this;
}
public Mail setReply(String... reply) {
this.reply = reply;
return this;
}
public Mail setTitle(String title) {
this.title = title;
return this;
}
public Mail setContent(String content) {
this.content = content;
return this;
}
public Mail setHtml(boolean isHtml) {
this.isHtml = isHtml;
return this;
}
public Mail setContent(String content, boolean isHtml) {
setContent(content);
return setHtml(isHtml);
}
public Mail setFiles(File... files) {
if (ArrayUtil.isEmpty(files)) {
return this;
}
final DataSource[] attachments = new DataSource[files.length];
for (int i = 0; i < files.length; i++) {
attachments[i] = new FileDataSource(files[i]);
}
return setAttachments(attachments);
}
public Mail setAttachments(DataSource... attachments) {
if (ArrayUtil.isNotEmpty(attachments)) {
final Charset charset = this.mailAccount.getCharset();
MimeBodyPart bodyPart;
String nameEncoded;
try {
for (DataSource attachment : attachments) {
bodyPart = new MimeBodyPart();
bodyPart.setDataHandler(new DataHandler(attachment));
nameEncoded = attachment.getName();
if (this.mailAccount.isEncodefilename()) {
nameEncoded = InternalMailUtil.encodeText(nameEncoded, charset);
}
bodyPart.setFileName(nameEncoded);
if (StrUtil.startWith(attachment.getContentType(), "image/")) {
bodyPart.setContentID(nameEncoded);
}
this.multipart.addBodyPart(bodyPart);
}
} catch (MessagingException e) {
throw new MailException(e);
}
}
return this;
}
public Mail addImage(String cid, InputStream imageStream) {
return addImage(cid, imageStream, null);
}
public Mail addImage(String cid, InputStream imageStream, String contentType) {
ByteArrayDataSource imgSource;
try {
imgSource = new ByteArrayDataSource(imageStream, ObjectUtil.defaultIfNull(contentType, "image/jpeg"));
} catch (IOException e) {
throw new IORuntimeException(e);
}
imgSource.setName(cid);
return setAttachments(imgSource);
}
public Mail addImage(String cid, File imageFile) {
InputStream in = null;
try {
in = FileUtil.getInputStream(imageFile);
return addImage(cid, in, FileTypeMap.getDefaultFileTypeMap().getContentType(imageFile));
} finally {
IoUtil.close(in);
}
}
public Mail setCharset(Charset charset) {
this.mailAccount.setCharset(charset);
return this;
}
public Mail setUseGlobalSession(boolean isUseGlobalSession) {
this.useGlobalSession = isUseGlobalSession;
return this;
}
public Mail setDebugOutput(PrintStream debugOutput) {
this.debugOutput = debugOutput;
return this;
}
@Override
public MimeMessage build() {
try {
return buildMsg();
} catch (MessagingException e) {
throw new MailException(e);
}
}
public String send() throws MailException {
try {
return doSend();
} catch (MessagingException e) {
if (e instanceof SendFailedException) {
final Address[] invalidAddresses = ((SendFailedException) e).getInvalidAddresses();
final String msg = StrUtil.format("Invalid Addresses: {}", ArrayUtil.toString(invalidAddresses));
throw new MailException(msg, e);
}
throw new MailException(e);
}
}
private String doSend() throws MessagingException {
final MimeMessage mimeMessage = buildMsg();
Transport.send(mimeMessage);
return mimeMessage.getMessageID();
}
private MimeMessage buildMsg() throws MessagingException {
final Charset charset = this.mailAccount.getCharset();
final MimeMessage msg = new MimeMessage(getSession());
final String from = this.mailAccount.getFrom();
if (StrUtil.isEmpty(from)) {
msg.setFrom();
} else {
msg.setFrom(InternalMailUtil.parseFirstAddress(from, charset));
}
msg.setSubject(this.title, (null == charset) ? null : charset.name());
msg.setSentDate(new Date());
msg.setContent(buildContent(charset));
msg.setRecipients(MimeMessage.RecipientType.TO, InternalMailUtil.parseAddressFromStrs(this.tos, charset));
if (ArrayUtil.isNotEmpty(this.ccs)) {
msg.setRecipients(MimeMessage.RecipientType.CC, InternalMailUtil.parseAddressFromStrs(this.ccs, charset));
}
if (ArrayUtil.isNotEmpty(this.bccs)) {
msg.setRecipients(MimeMessage.RecipientType.BCC, InternalMailUtil.parseAddressFromStrs(this.bccs, charset));
}
if (ArrayUtil.isNotEmpty(this.reply)) {
msg.setReplyTo(InternalMailUtil.parseAddressFromStrs(this.reply, charset));
}
return msg;
}
private Multipart buildContent(Charset charset) throws MessagingException {
final String charsetStr = null != charset ? charset.name() : MimeUtility.getDefaultJavaCharset();
final MimeBodyPart body = new MimeBodyPart();
body.setContent(content, StrUtil.format("text/{}; charset={}", isHtml ? "html" : "plain", charsetStr));
this.multipart.addBodyPart(body);
return this.multipart;
}
private Session getSession() {
final Session session = MailUtils.getSession(this.mailAccount, this.useGlobalSession);
if (null != this.debugOutput) {
session.setDebugOut(debugOutput);
}
return session;
}
}
邮件账户对象
package com.xueyi.common.mail.utils;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.Setting;
import java.io.Serial;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class MailAccount implements Serializable {
@Serial
private static final long serialVersionUID = -6937313421815719204L;
private static final String MAIL_PROTOCOL = "mail.transport.protocol";
private static final String SMTP_HOST = "mail.smtp.host";
private static final String SMTP_PORT = "mail.smtp.port";
private static final String SMTP_AUTH = "mail.smtp.auth";
private static final String SMTP_TIMEOUT = "mail.smtp.timeout";
private static final String SMTP_CONNECTION_TIMEOUT = "mail.smtp.connectiontimeout";
private static final String SMTP_WRITE_TIMEOUT = "mail.smtp.writetimeout";
private static final String STARTTLS_ENABLE = "mail.smtp.starttls.enable";
private static final String SSL_ENABLE = "mail.smtp.ssl.enable";
private static final String SSL_PROTOCOLS = "mail.smtp.ssl.protocols";
private static final String SOCKET_FACTORY = "mail.smtp.socketFactory.class";
private static final String SOCKET_FACTORY_FALLBACK = "mail.smtp.socketFactory.fallback";
private static final String SOCKET_FACTORY_PORT = "smtp.socketFactory.port";
private static final String SPLIT_LONG_PARAMS = "mail.mime.splitlongparameters";
private static final String MAIL_DEBUG = "mail.debug";
public static final String[] MAIL_SETTING_PATHS = new String[]{"config/mail.setting", "config/mailAccount.setting", "mail.setting"};
private String host;
private Integer port;
private Boolean auth;
private String user;
private String pass;
private String from;
private boolean debug;
private Charset charset = CharsetUtil.CHARSET_UTF_8;
private boolean splitlongparameters = false;
private boolean encodefilename = true;
private boolean starttlsEnable = false;
private Boolean sslEnable;
private String sslProtocols;
private String socketFactoryClass = "javax.net.ssl.SSLSocketFactory";
private boolean socketFactoryFallback;
private int socketFactoryPort = 465;
private long timeout;
private long connectionTimeout;
private long writeTimeout;
private final Map<String, Object> customProperty = new HashMap<>();
public MailAccount() {
}
public MailAccount(String settingPath) {
this(new Setting(settingPath));
}
public MailAccount(Setting setting) {
setting.toBean(this);
}
public String getHost() {
return host;
}
public MailAccount setHost(String host) {
this.host = host;
return this;
}
public Integer getPort() {
return port;
}
public MailAccount setPort(Integer port) {
this.port = port;
return this;
}
public Boolean isAuth() {
return auth;
}
public MailAccount setAuth(boolean isAuth) {
this.auth = isAuth;
return this;
}
public String getUser() {
return user;
}
public MailAccount setUser(String user) {
this.user = user;
return this;
}
public String getPass() {
return pass;
}
public MailAccount setPass(String pass) {
this.pass = pass;
return this;
}
public String getFrom() {
return from;
}
public MailAccount setFrom(String from) {
this.from = from;
return this;
}
public boolean isDebug() {
return debug;
}
public MailAccount setDebug(boolean debug) {
this.debug = debug;
return this;
}
public Charset getCharset() {
return charset;
}
public MailAccount setCharset(Charset charset) {
this.charset = charset;
return this;
}
public boolean isSplitlongparameters() {
return splitlongparameters;
}
public void setSplitlongparameters(boolean splitlongparameters) {
this.splitlongparameters = splitlongparameters;
}
public boolean isEncodefilename() {
return encodefilename;
}
public void setEncodefilename(boolean encodefilename) {
this.encodefilename = encodefilename;
}
public boolean isStarttlsEnable() {
return this.starttlsEnable;
}
public MailAccount setStarttlsEnable(boolean startttlsEnable) {
this.starttlsEnable = startttlsEnable;
return this;
}
public Boolean isSslEnable() {
return this.sslEnable;
}
public MailAccount setSslEnable(Boolean sslEnable) {
this.sslEnable = sslEnable;
return this;
}
public String getSslProtocols() {
return sslProtocols;
}
public void setSslProtocols(String sslProtocols) {
this.sslProtocols = sslProtocols;
}
public String getSocketFactoryClass() {
return socketFactoryClass;
}
public MailAccount setSocketFactoryClass(String socketFactoryClass) {
this.socketFactoryClass = socketFactoryClass;
return this;
}
public boolean isSocketFactoryFallback() {
return socketFactoryFallback;
}
public MailAccount setSocketFactoryFallback(boolean socketFactoryFallback) {
this.socketFactoryFallback = socketFactoryFallback;
return this;
}
public int getSocketFactoryPort() {
return socketFactoryPort;
}
public MailAccount setSocketFactoryPort(int socketFactoryPort) {
this.socketFactoryPort = socketFactoryPort;
return this;
}
public MailAccount setTimeout(long timeout) {
this.timeout = timeout;
return this;
}
public MailAccount setConnectionTimeout(long connectionTimeout) {
this.connectionTimeout = connectionTimeout;
return this;
}
public MailAccount setWriteTimeout(long writeTimeout) {
this.writeTimeout = writeTimeout;
return this;
}
public Map<String, Object> getCustomProperty() {
return customProperty;
}
public MailAccount setCustomProperty(String key, Object value) {
if (StrUtil.isNotBlank(key) && ObjectUtil.isNotNull(value)) {
this.customProperty.put(key, value);
}
return this;
}
public Properties getSmtpProps() {
System.setProperty(SPLIT_LONG_PARAMS, String.valueOf(this.splitlongparameters));
final Properties p = new Properties();
p.put(MAIL_PROTOCOL, "smtp");
p.put(SMTP_HOST, this.host);
p.put(SMTP_PORT, String.valueOf(this.port));
p.put(SMTP_AUTH, String.valueOf(this.auth));
if (this.timeout > 0) {
p.put(SMTP_TIMEOUT, String.valueOf(this.timeout));
}
if (this.connectionTimeout > 0) {
p.put(SMTP_CONNECTION_TIMEOUT, String.valueOf(this.connectionTimeout));
}
if (this.writeTimeout > 0) {
p.put(SMTP_WRITE_TIMEOUT, String.valueOf(this.writeTimeout));
}
p.put(MAIL_DEBUG, String.valueOf(this.debug));
if (this.starttlsEnable) {
p.put(STARTTLS_ENABLE, "true");
if (null == this.sslEnable) {
this.sslEnable = true;
}
}
if (null != this.sslEnable && this.sslEnable) {
p.put(SSL_ENABLE, "true");
p.put(SOCKET_FACTORY, socketFactoryClass);
p.put(SOCKET_FACTORY_FALLBACK, String.valueOf(this.socketFactoryFallback));
p.put(SOCKET_FACTORY_PORT, String.valueOf(this.socketFactoryPort));
if (StrUtil.isNotBlank(this.sslProtocols)) {
p.put(SSL_PROTOCOLS, this.sslProtocols);
}
}
p.putAll(this.customProperty);
return p;
}
public MailAccount defaultIfEmpty() {
final String fromAddress = InternalMailUtil.parseFirstAddress(this.from, this.charset).getAddress();
if (StrUtil.isBlank(this.host)) {
this.host = StrUtil.format("smtp.{}", StrUtil.subSuf(fromAddress, fromAddress.indexOf('@') + 1));
}
if (StrUtil.isBlank(user)) {
this.user = fromAddress;
}
if (null == this.auth) {
this.auth = (false == StrUtil.isBlank(this.pass));
}
if (null == this.port) {
this.port = (null != this.sslEnable && this.sslEnable) ? this.socketFactoryPort : 25;
}
if (null == this.charset) {
this.charset = CharsetUtil.CHARSET_UTF_8;
}
return this;
}
@Override
public String toString() {
return "MailAccount [host=" + host + ", port=" + port + ", auth=" + auth + ", user=" + user + ", pass=" + (StrUtil.isEmpty(this.pass) ? "" : "******") + ", from=" + from + ", startttlsEnable="
+ starttlsEnable + ", socketFactoryClass=" + socketFactoryClass + ", socketFactoryFallback=" + socketFactoryFallback + ", socketFactoryPort=" + socketFactoryPort + "]";
}
}
邮件异常工具类
package com.xueyi.common.mail.utils;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import java.io.Serial;
public class MailException extends RuntimeException {
@Serial
private static final long serialVersionUID = 8247610319171014183L;
public MailException(Throwable e) {
super(ExceptionUtil.getMessage(e), e);
}
public MailException(String message) {
super(message);
}
public MailException(String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params));
}
public MailException(String message, Throwable throwable) {
super(message, throwable);
}
public MailException(String message, Throwable throwable, boolean enableSuppression, boolean writableStackTrace) {
super(message, throwable, enableSuppression, writableStackTrace);
}
public MailException(Throwable throwable, String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params), throwable);
}
}
邮件工具类
package com.xueyi.common.mail.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import jakarta.mail.Authenticator;
import jakarta.mail.Session;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.io.File;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MailUtils {
private static final MailAccount ACCOUNT = SpringUtil.getBean(MailAccount.class);
public static MailAccount getMailAccount() {
return ACCOUNT;
}
public static MailAccount getMailAccount(String from, String user, String pass) {
ACCOUNT.setFrom(StrUtil.blankToDefault(from, ACCOUNT.getFrom()));
ACCOUNT.setUser(StrUtil.blankToDefault(user, ACCOUNT.getUser()));
ACCOUNT.setPass(StrUtil.blankToDefault(pass, ACCOUNT.getPass()));
return ACCOUNT;
}
public static String sendText(String to, String subject, String content, File... files) {
return send(to, subject, content, false, files);
}
public static String sendHtml(String to, String subject, String content, File... files) {
return send(to, subject, content, true, files);
}
public static String send(String to, String subject, String content, boolean isHtml, File... files) {
return send(splitAddress(to), subject, content, isHtml, files);
}
public static String send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) {
return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files);
}
public static String sendText(Collection<String> tos, String subject, String content, File... files) {
return send(tos, subject, content, false, files);
}
public static String sendHtml(Collection<String> tos, String subject, String content, File... files) {
return send(tos, subject, content, true, files);
}
public static String send(Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
return send(tos, null, null, subject, content, isHtml, files);
}
public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
return send(getMailAccount(), true, tos, ccs, bccs, subject, content, null, isHtml, files);
}
public static String send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) {
return send(mailAccount, splitAddress(to), subject, content, isHtml, files);
}
public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
return send(mailAccount, tos, null, null, subject, content, isHtml, files);
}
public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
return send(mailAccount, false, tos, ccs, bccs, subject, content, null, isHtml, files);
}
public static String sendHtml(String to, String subject, String content, Map<String, InputStream> imageMap, File... files) {
return send(to, subject, content, imageMap, true, files);
}
public static String send(String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(splitAddress(to), subject, content, imageMap, isHtml, files);
}
public static String send(String to, String cc, String bcc, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, imageMap, isHtml, files);
}
public static String sendHtml(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, File... files) {
return send(tos, subject, content, imageMap, true, files);
}
public static String send(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(tos, null, null, subject, content, imageMap, isHtml, files);
}
public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(getMailAccount(), true, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
}
public static String send(MailAccount mailAccount, String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(mailAccount, splitAddress(to), subject, content, imageMap, isHtml, files);
}
public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
return send(mailAccount, tos, null, null, subject, content, imageMap, isHtml, files);
}
public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap,
boolean isHtml, File... files) {
return send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
}
public static Session getSession(MailAccount mailAccount, boolean isSingleton) {
Authenticator authenticator = null;
if (mailAccount.isAuth()) {
authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass());
}
return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator)
: Session.getInstance(mailAccount.getSmtpProps(), authenticator);
}
private static String send(MailAccount mailAccount, boolean useGlobalSession, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content,
Map<String, InputStream> imageMap, boolean isHtml, File... files) {
final Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession);
if (CollUtil.isNotEmpty(ccs)) {
mail.setCcs(ccs.toArray(new String[0]));
}
if (CollUtil.isNotEmpty(bccs)) {
mail.setBccs(bccs.toArray(new String[0]));
}
mail.setTos(tos.toArray(new String[0]));
mail.setTitle(subject);
mail.setContent(content);
mail.setHtml(isHtml);
mail.setFiles(files);
if (MapUtil.isNotEmpty(imageMap)) {
for (Map.Entry<String, InputStream> entry : imageMap.entrySet()) {
mail.addImage(entry.getKey(), entry.getValue());
IoUtil.close(entry.getValue());
}
}
return mail.send();
}
private static List<String> splitAddress(String addresses) {
if (StrUtil.isBlank(addresses)) {
return null;
}
List<String> result;
if (StrUtil.contains(addresses, CharUtil.COMMA)) {
result = StrUtil.splitTrim(addresses, CharUtil.COMMA);
} else if (StrUtil.contains(addresses, ';')) {
result = StrUtil.splitTrim(addresses, ';');
} else {
result = CollUtil.newArrayList(addresses);
}
return result;
}
}
邮件用户名密码验证器
package com.xueyi.common.mail.utils;
import jakarta.mail.Authenticator;
import jakarta.mail.PasswordAuthentication;
public class UserPassAuthenticator extends Authenticator {
private final String user;
private final String pass;
public UserPassAuthenticator(String user, String pass) {
this.user = user;
this.pass = pass;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(this.user, this.pass);
}
}
Redis使用FastJson序列化
package com.xueyi.common.redis.configure;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.Filter;
import com.xueyi.common.core.constant.basic.Constants;
import com.xueyi.common.core.utils.core.ArrayUtil;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR);
private Class<T> clazz;
public FastJson2JsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (ArrayUtil.isEmpty(bytes)) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
}
}
redis配置
package com.xueyi.common.redis.configure;
import com.xueyi.common.core.utils.core.ObjectUtil;
import com.xueyi.common.core.utils.core.StrUtil;
import lombok.Data;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Data
@Configuration
@EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class)
@ConfigurationProperties(prefix = "spring.data.redis")
public class RedisConfig {
private String host;
private Integer port;
private String password;
private int database;
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration conf = new RedisStandaloneConfiguration(host, port);
if (StrUtil.isNotBlank(password)) {
conf.setPassword(password);
}
if (ObjectUtil.isNotNull(database)) {
conf.setDatabase(database);
}
return new LettuceConnectionFactory(conf);
}
@Bean
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
@Bean("redisJavaTemplate")
public RedisTemplate<Object, Object> redisJavaTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(RedisSerializer.java());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(RedisSerializer.java());
template.afterPropertiesSet();
return template;
}
}
缓存 通用常量
package com.xueyi.common.redis.constant;
import com.xueyi.common.core.utils.core.EnumUtil;
import com.xueyi.common.core.utils.core.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
public class RedisConstants {
@Getter
@AllArgsConstructor
public enum CacheKey {
CLIENT_DETAILS_KEY("client:details", "oauth 客户端信息"),
CAPTCHA_CODE_KEY("captcha_codes:", "验证码"),
SYS_CORRELATE_KEY("system:correlate:{}.{}", "数据关联工具"),
SYS_CORRELATE_IMPL_KEY("system:correlate:service:{}", "数据关联工具"),
DICT_KEY("system:dict:{}", "字典缓存"),
CONFIG_KEY("system:config:{}", "参数缓存");
private final String code;
private final String info;
public String getCacheName(Object... cacheNames) {
return StrUtil.format(getCode(), cacheNames);
}
}
@Getter
@AllArgsConstructor
public enum OperateType {
REFRESH_ALL("refresh_all", "更新全部"),
REFRESH("refresh", "更新"),
REMOVE("remove", "删除");
private final String code;
private final String info;
public static OperateType getByCode(String code) {
return EnumUtil.getByCode(OperateType.class, code);
}
}
}
spring redis 工具类
package com.xueyi.common.redis.service;
import com.xueyi.common.core.exception.UtilException;
import com.xueyi.common.core.utils.core.ArrayUtil;
import com.xueyi.common.core.utils.core.CollUtil;
import com.xueyi.common.core.utils.core.MapUtil;
import com.xueyi.common.core.utils.core.NumberUtil;
import com.xueyi.common.core.utils.core.ObjectUtil;
import com.xueyi.common.core.utils.core.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@Component
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public class RedisService {
@Autowired
public RedisTemplate redisTemplate;
@Autowired
@Qualifier("redisJavaTemplate")
public RedisTemplate redisJavaTemplate;
public <T> void setJavaCacheObject(final String key, final T value) {
setJavaCacheObject(key, value, NumberUtil.Nine, TimeUnit.HOURS);
}
public <T> void setJavaCacheObject(final String key, final T value, final long timeout, final TimeUnit timeUnit) {
redisJavaTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
public <T> T getJavaCacheObject(final String key) {
ValueOperations<String, T> operation = redisJavaTemplate.opsForValue();
return operation.get(key);
}
public <T> void setJavaCacheMap(final String key, final Map<String, T> dataMap) {
setJavaCacheMap(key, dataMap, NumberUtil.Nine, TimeUnit.HOURS);
}
public <T> void setJavaCacheMap(final String key, final Map<String, T> dataMap, final long timeout, final TimeUnit unit) {
if (dataMap != null) {
redisJavaTemplate.opsForHash().putAll(key, dataMap);
expireJava(key, timeout, unit);
}
}
public <T> Map<String, T> getJavaCacheMap(final String key) {
return redisJavaTemplate.opsForHash().entries(key);
}
public <T> void setJavaCacheMapValue(final String key, final String hKey, final T value) {
redisJavaTemplate.opsForHash().put(key, hKey, value);
}
public <T> T getJavaCacheMapValue(final String key, final String hKey) {
HashOperations<String, String, T> opsForHash = redisJavaTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
public Boolean hasJavaKey(String key) {
return redisJavaTemplate.hasKey(key);
}
public Boolean expireJava(final String key, final long timeout, final TimeUnit unit) {
return redisJavaTemplate.expire(key, timeout, unit);
}
public <T> void setCacheObject(final String key, final T value) {
redisTemplate.opsForValue().set(key, value);
}
public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
public boolean expire(final String key, final long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
public Boolean expire(final String key, final long timeout, final TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
public Long getExpire(final String key) {
return redisTemplate.getExpire(key);
}
public Boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
public <T> T getCacheObject(final String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
public Boolean deleteObject(final String key) {
return redisTemplate.delete(key);
}
public Long deleteObject(final Collection collection) {
return redisTemplate.delete(collection);
}
public <T> long setCacheList(final String key, final List<T> dataList) {
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
public <T> long setCacheList(final String key, final List<T> dataList, final long timeout, final TimeUnit unit) {
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
if (ObjectUtil.isNotNull(count)) {
expire(key, timeout, unit);
}
return count == null ? 0 : count;
}
public <T> List<T> getCacheList(final String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
for (T t : dataSet) {
setOperation.add(t);
}
return setOperation;
}
public <T> Set<T> getCacheSet(final String key) {
return redisTemplate.opsForSet().members(key);
}
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
public <T> void setCacheMap(final String key, final Map<String, T> dataMap, final long timeout, final TimeUnit unit) {
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
expire(key, timeout, unit);
}
}
public <T> Map<String, T> getCacheMap(final String key) {
return redisTemplate.opsForHash().entries(key);
}
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
redisTemplate.opsForHash().put(key, hKey, value);
}
public <T> T getCacheMapValue(final String key, final String hKey) {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
public boolean deleteCacheMapValue(final String key, final String hKey) {
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
public boolean deleteCacheMapValue(final String key, final Object[] hKey) {
return redisTemplate.opsForHash().delete(key, hKey) > 0;
}
public Collection<String> keys(final String pattern) {
return redisTemplate.keys(pattern);
}
public <T> void refreshListCache(String optionKey, List<T> dataList) {
setCacheList(optionKey, dataList, NumberUtil.Nine, TimeUnit.HOURS);
}
public <T, K> void refreshMapCache(String mapKey, Collection<T> cacheList, Function<? super T, String> keyGet, Function<? super T, K> valueGet) {
Map<String, K> resultMap = new HashMap<>();
if (CollUtil.isNotEmpty(cacheList)) {
resultMap = cacheList.stream()
.filter(item -> {
if (StrUtil.isEmpty(keyGet.apply(item))) {
throw new UtilException("cache key cannot be empty");
}
return ObjectUtil.isNotNull(valueGet.apply(item));
}).collect(Collectors.toMap(keyGet, valueGet));
}
if (MapUtil.isNotEmpty(resultMap)) {
setCacheMap(mapKey, resultMap, NumberUtil.Nine, TimeUnit.HOURS);
} else {
deleteObject(mapKey);
}
}
public <T> void refreshMapValueCache(String mapKey, Supplier<Serializable> keyGet, Supplier<T> valueGet) {
if (ObjectUtil.isNotNull(valueGet.get())) {
setCacheMapValue(mapKey, keyGet.get().toString(), valueGet.get());
} else {
deleteCacheMapValue(mapKey, keyGet.get().toString());
}
if (hasKey(mapKey)) {
expire(mapKey, NumberUtil.Nine, TimeUnit.HOURS);
}
}
public void removeMapValueCache(String mapKey, Serializable... keys) {
if (ArrayUtil.isNotEmpty(keys)) {
deleteCacheMapValue(mapKey, keys);
}
}
}
Token解析器
package com.xueyi.common.security.handler;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.basic.TokenConstants;
import com.xueyi.common.core.utils.core.ArrayUtil;
import com.xueyi.common.core.utils.core.StrUtil;
import com.xueyi.common.core.utils.servlet.ServletUtil;
import com.xueyi.common.security.config.properties.PermitAllUrlProperties;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.MediaType;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.server.resource.BearerTokenError;
import org.springframework.security.oauth2.server.resource.BearerTokenErrors;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BearerTokenHandler implements BearerTokenResolver {
private static final Pattern authorizationPattern = Pattern.compile("^Bearer (?[a-zA-Z0-9-:._~+/]+=*)$", Pattern.CASE_INSENSITIVE);
private boolean allowFormEncodedBodyParameter = false;
private boolean allowUriQueryParameter = true;
private final PathMatcher pathMatcher = new AntPathMatcher();
private final PermitAllUrlProperties urlProperties;
public BearerTokenHandler(PermitAllUrlProperties urlProperties) {
this.urlProperties = urlProperties;
}
@Override
public String resolve(HttpServletRequest request) {
AtomicBoolean match = new AtomicBoolean(urlProperties.getRoutine().stream().anyMatch(url ->
pathMatcher.match(url, request.getRequestURI())));
if (!match.get()) {
Optional.ofNullable(urlProperties.getCustom().get(RequestMethod.valueOf(request.getMethod())))
.ifPresent(list -> match.set(list.stream().anyMatch(url -> pathMatcher.match(url, request.getRequestURI()))));
}
if (match.get()) {
return null;
}
final String authorizationHeaderToken = resolveFromAuthorizationHeader(request);
final String parameterToken = isParameterTokenSupportedForRequest(request) ? resolveFromRequestParameters(request) : null;
if (authorizationHeaderToken != null) {
if (parameterToken != null) {
final BearerTokenError error = BearerTokenErrors
.invalidRequest("Found multiple bearer tokens in the request");
throw new OAuth2AuthenticationException(error);
}
return authorizationHeaderToken;
}
if (parameterToken != null && isParameterTokenEnabledForRequest(request)) {
return parameterToken;
}
return null;
}
private String resolveFromAuthorizationHeader(HttpServletRequest request) {
String authorization = ServletUtil.getHeader(request, SecurityConstants.BaseSecurity.ACCESS_TOKEN.getCode());
if (!StrUtil.startWith(authorization, TokenConstants.PREFIX))
return null;
Matcher matcher = authorizationPattern.matcher(authorization);
if (!matcher.matches()) {
BearerTokenError error = BearerTokenErrors.invalidToken("Bearer token is malformed");
throw new OAuth2AuthenticationException(error);
}
return matcher.group("token");
}
private static String resolveFromRequestParameters(HttpServletRequest request) {
String[] values = request.getParameterValues(SecurityConstants.BaseSecurity.ACCESS_TOKEN.getCode());
if (ArrayUtil.isEmpty(values)) {
return null;
}
if (values.length == 1) {
return values[0];
}
BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
throw new OAuth2AuthenticationException(error);
}
private boolean isParameterTokenSupportedForRequest(final HttpServletRequest request) {
return (("POST".equals(request.getMethod())
&& MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType()))
|| "GET".equals(request.getMethod()));
}
private boolean isParameterTokenEnabledForRequest(final HttpServletRequest request) {
return ((this.allowFormEncodedBodyParameter && "POST".equals(request.getMethod())
&& MediaType.APPLICATION_FORM_URLENCODED_VALUE.equals(request.getContentType()))
|| (this.allowUriQueryParameter && "GET".equals(request.getMethod())));
}
}
Redis授权认证器
package com.xueyi.common.security.handler;
import com.xueyi.common.core.utils.core.NumberUtil;
import com.xueyi.common.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.concurrent.TimeUnit;
@Component
public class RedisOAuth2AuthorizationConsentHandler implements OAuth2AuthorizationConsentService {
@Autowired
private RedisService redisService;
@Override
public void save(OAuth2AuthorizationConsent authorizationConsent) {
Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");
redisService.setCacheObject(buildKey(authorizationConsent), authorizationConsent, (long) NumberUtil.Ten, TimeUnit.MINUTES);
}
@Override
public void remove(OAuth2AuthorizationConsent authorizationConsent) {
Assert.notNull(authorizationConsent, "authorizationConsent cannot be null");
redisService.deleteObject(buildKey(authorizationConsent));
}
@Override
public OAuth2AuthorizationConsent findById(String registeredClientId, String principalName) {
Assert.hasText(registeredClientId, "registeredClientId cannot be empty");
Assert.hasText(principalName, "principalName cannot be empty");
OAuth2AuthorizationConsent authorizationConsent = redisService.getCacheObject(buildKey(registeredClientId, principalName));
return authorizationConsent;
}
private static String buildKey(String registeredClientId, String principalName) {
return "token:consent:" + registeredClientId + ":" + principalName;
}
private static String buildKey(OAuth2AuthorizationConsent authorizationConsent) {
return buildKey(authorizationConsent.getRegisteredClientId(), authorizationConsent.getPrincipalName());
}
}
Redis授权
package com.xueyi.common.security.handler;
import com.xueyi.common.core.utils.core.ObjectUtil;
import com.xueyi.common.core.web.model.BaseLoginUser;
import com.xueyi.common.redis.service.RedisService;
import com.xueyi.common.security.service.ITokenService;
import com.xueyi.common.security.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.Objects;
import java.util.Optional;
@Component
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public class RedisOAuth2AuthorizationHandler implements OAuth2AuthorizationService {
@Autowired
private RedisService redisService;
@Override
public void save(OAuth2Authorization authorization) {
BaseLoginUser loginUser = SecurityUtils.getLoginUser(authorization);
ITokenService tokenService = SecurityUtils.getTokenService(loginUser.getAccountType().getCode());
if (isRefreshToken(authorization)) {
String refreshToken = Optional.ofNullable(authorization.getRefreshToken())
.map(OAuth2Authorization.Token::getToken)
.map(OAuth2RefreshToken::getTokenValue)
.orElseThrow(() -> new NullPointerException("refreshToken cannot be null"));
loginUser.setRefreshToken(tokenService.getTokenAddress(OAuth2ParameterNames.REFRESH_TOKEN, loginUser.getEnterpriseId(), loginUser.getUserId(), refreshToken));
}
if (isAccessToken(authorization)) {
String accessToken = Optional.ofNullable(authorization.getAccessToken())
.map(OAuth2Authorization.Token::getToken)
.map(OAuth2AccessToken::getTokenValue)
.orElseThrow(() -> new NullPointerException("accessToken cannot be null"));
loginUser.setAccessToken(tokenService.getTokenAddress(OAuth2ParameterNames.ACCESS_TOKEN, loginUser.getEnterpriseId(), loginUser.getUserId(), accessToken));
}
if (isState(authorization)) {
String token = authorization.getAttribute(OAuth2ParameterNames.STATE);
loginUser.setStateToken(tokenService.getTokenAddress(OAuth2ParameterNames.STATE, loginUser.getEnterpriseId(), loginUser.getUserId(), token));
}
if (isCode(authorization)) {
OAuth2AuthorizationCode authorizationCodeToken = Optional.ofNullable(authorization.getToken(OAuth2AuthorizationCode.class))
.map(OAuth2Authorization.Token::getToken)
.orElseThrow(() -> new NullPointerException("authorizationCodeToken cannot be null"));
loginUser.setCodeToken(tokenService.getTokenAddress(OAuth2ParameterNames.CODE, loginUser.getEnterpriseId(), loginUser.getUserId(), authorizationCodeToken.getTokenValue()));
}
tokenService.createTokenCache(authorization);
}
@Override
public void remove(OAuth2Authorization authorization) {
BaseLoginUser loginUser = SecurityUtils.getLoginUser(authorization);
ITokenService tokenService = SecurityUtils.getTokenService(loginUser.getAccountType().getCode());
tokenService.removeTokenCache(loginUser);
}
@Override
@Nullable
public OAuth2Authorization findById(String id) {
throw new UnsupportedOperationException();
}
@Override
@Nullable
public OAuth2Authorization findByToken(String token, @Nullable OAuth2TokenType tokenType) {
Assert.hasText(token, "token cannot be empty");
Assert.notNull(tokenType, "tokenType cannot be empty");
return ObjectUtil.equals(OAuth2TokenType.ACCESS_TOKEN, tokenType) ? redisService.getJavaCacheObject(token) : ObjectUtil.equals(OAuth2TokenType.REFRESH_TOKEN, tokenType) ? redisService.getCacheObject(token) : null;
}
private static boolean isState(OAuth2Authorization authorization) {
return Objects.nonNull(authorization.getAttribute(OAuth2ParameterNames.STATE));
}
private static boolean isCode(OAuth2Authorization authorization) {
OAuth2Authorization.Token<OAuth2AuthorizationCode> authorizationCode = authorization.getToken(OAuth2AuthorizationCode.class);
return ObjectUtil.isNotNull(authorizationCode);
}
private static boolean isRefreshToken(OAuth2Authorization authorization) {
return ObjectUtil.isNotNull(authorization.getRefreshToken());
}
private static boolean isAccessToken(OAuth2Authorization authorization) {
return ObjectUtil.isNotNull(authorization.getAccessToken());
}
}
文件上传工具类
package com.xueyi.file.utils;
import com.xueyi.common.core.exception.file.FileException;
import com.xueyi.common.core.exception.file.FileNameLengthLimitExceededException;
import com.xueyi.common.core.exception.file.FileSizeLimitExceededException;
import com.xueyi.common.core.exception.file.InvalidExtensionException;
import com.xueyi.common.core.utils.DateUtil;
import com.xueyi.common.core.utils.core.IdUtil;
import com.xueyi.common.core.utils.core.StrUtil;
import com.xueyi.common.core.utils.file.FileTypeUtil;
import com.xueyi.common.core.utils.file.MimeTypeUtil;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
public class FileUploadUtils {
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
public static String upload(String baseDir, MultipartFile file) throws IOException {
try {
return upload(baseDir, file, MimeTypeUtil.DEFAULT_ALLOWED_EXTENSION);
} catch (FileException fe) {
throw new IOException(fe.getDefaultMessage(), fe);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
public static String upload(String baseDir, MultipartFile file, String[] allowedExtension) throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, InvalidExtensionException {
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(fileName);
}
public static String extractFilename(MultipartFile file) {
return StrUtil.format("{}/{}_{}.{}", DateUtil.datePath(), FilenameUtils.getBaseName(file.getOriginalFilename()), IdUtil.simpleUUID(), FileTypeUtil.getExtension(file));
}
private static File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists()) {
if (!desc.getParentFile().exists()) {
desc.getParentFile().mkdirs();
}
}
return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
}
private static String getPathFileName(String fileName) {
return StrUtil.SLASH + fileName;
}
public static void assertAllowed(MultipartFile file, String[] allowedExtension) throws FileSizeLimitExceededException, InvalidExtensionException {
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE) {
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = FileTypeUtil.getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
if (allowedExtension == MimeTypeUtil.IMAGE_EXTENSION) {
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, fileName);
} else if (allowedExtension == MimeTypeUtil.FLASH_EXTENSION) {
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, fileName);
} else if (allowedExtension == MimeTypeUtil.MEDIA_EXTENSION) {
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, fileName);
} else if (allowedExtension == MimeTypeUtil.VIDEO_EXTENSION) {
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, fileName);
} else {
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
public static boolean isAllowedExtension(String extension, String[] allowedExtension) {
for (String str : allowedExtension) {
if (str.equalsIgnoreCase(extension)) {
return true;
}
}
return false;
}
}