jdk 17
This commit is contained in:
2
idp/backend/idp-starter/.gitattributes
vendored
Normal file
2
idp/backend/idp-starter/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/mvnw text eol=lf
|
||||
*.cmd text eol=crlf
|
||||
33
idp/backend/idp-starter/.gitignore
vendored
Normal file
33
idp/backend/idp-starter/.gitignore
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
HELP.md
|
||||
target/
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
295
idp/backend/idp-starter/mvnw
vendored
Normal file
295
idp/backend/idp-starter/mvnw
vendored
Normal file
@@ -0,0 +1,295 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Apache Maven Wrapper startup batch script, version 3.3.4
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
|
||||
# MVNW_REPOURL - repo url base for downloading maven distribution
|
||||
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
set -euf
|
||||
[ "${MVNW_VERBOSE-}" != debug ] || set -x
|
||||
|
||||
# OS specific support.
|
||||
native_path() { printf %s\\n "$1"; }
|
||||
case "$(uname)" in
|
||||
CYGWIN* | MINGW*)
|
||||
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
|
||||
native_path() { cygpath --path --windows "$1"; }
|
||||
;;
|
||||
esac
|
||||
|
||||
# set JAVACMD and JAVACCMD
|
||||
set_java_home() {
|
||||
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
|
||||
if [ -n "${JAVA_HOME-}" ]; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACCMD="$JAVA_HOME/jre/sh/javac"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACCMD="$JAVA_HOME/bin/javac"
|
||||
|
||||
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
|
||||
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
|
||||
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
JAVACMD="$(
|
||||
'set' +e
|
||||
'unset' -f command 2>/dev/null
|
||||
'command' -v java
|
||||
)" || :
|
||||
JAVACCMD="$(
|
||||
'set' +e
|
||||
'unset' -f command 2>/dev/null
|
||||
'command' -v javac
|
||||
)" || :
|
||||
|
||||
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
|
||||
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# hash string like Java String::hashCode
|
||||
hash_string() {
|
||||
str="${1:-}" h=0
|
||||
while [ -n "$str" ]; do
|
||||
char="${str%"${str#?}"}"
|
||||
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
|
||||
str="${str#?}"
|
||||
done
|
||||
printf %x\\n $h
|
||||
}
|
||||
|
||||
verbose() { :; }
|
||||
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
|
||||
|
||||
die() {
|
||||
printf %s\\n "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
trim() {
|
||||
# MWRAPPER-139:
|
||||
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
|
||||
# Needed for removing poorly interpreted newline sequences when running in more
|
||||
# exotic environments such as mingw bash on Windows.
|
||||
printf "%s" "${1}" | tr -d '[:space:]'
|
||||
}
|
||||
|
||||
scriptDir="$(dirname "$0")"
|
||||
scriptName="$(basename "$0")"
|
||||
|
||||
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
|
||||
while IFS="=" read -r key value; do
|
||||
case "${key-}" in
|
||||
distributionUrl) distributionUrl=$(trim "${value-}") ;;
|
||||
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
|
||||
esac
|
||||
done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
|
||||
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
|
||||
|
||||
case "${distributionUrl##*/}" in
|
||||
maven-mvnd-*bin.*)
|
||||
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
|
||||
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
|
||||
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
|
||||
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
|
||||
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
|
||||
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
|
||||
*)
|
||||
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
|
||||
distributionPlatform=linux-amd64
|
||||
;;
|
||||
esac
|
||||
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
|
||||
;;
|
||||
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
|
||||
*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
|
||||
esac
|
||||
|
||||
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
||||
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
||||
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
|
||||
distributionUrlName="${distributionUrl##*/}"
|
||||
distributionUrlNameMain="${distributionUrlName%.*}"
|
||||
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
|
||||
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
|
||||
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
|
||||
|
||||
exec_maven() {
|
||||
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
|
||||
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
|
||||
}
|
||||
|
||||
if [ -d "$MAVEN_HOME" ]; then
|
||||
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
||||
exec_maven "$@"
|
||||
fi
|
||||
|
||||
case "${distributionUrl-}" in
|
||||
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
|
||||
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
|
||||
esac
|
||||
|
||||
# prepare tmp dir
|
||||
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
|
||||
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
|
||||
trap clean HUP INT TERM EXIT
|
||||
else
|
||||
die "cannot create temp dir"
|
||||
fi
|
||||
|
||||
mkdir -p -- "${MAVEN_HOME%/*}"
|
||||
|
||||
# Download and Install Apache Maven
|
||||
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
||||
verbose "Downloading from: $distributionUrl"
|
||||
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||
|
||||
# select .zip or .tar.gz
|
||||
if ! command -v unzip >/dev/null; then
|
||||
distributionUrl="${distributionUrl%.zip}.tar.gz"
|
||||
distributionUrlName="${distributionUrl##*/}"
|
||||
fi
|
||||
|
||||
# verbose opt
|
||||
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
|
||||
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
|
||||
|
||||
# normalize http auth
|
||||
case "${MVNW_PASSWORD:+has-password}" in
|
||||
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||
esac
|
||||
|
||||
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
|
||||
verbose "Found wget ... using wget"
|
||||
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
|
||||
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
|
||||
verbose "Found curl ... using curl"
|
||||
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
|
||||
elif set_java_home; then
|
||||
verbose "Falling back to use Java to download"
|
||||
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
|
||||
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||
cat >"$javaSource" <<-END
|
||||
public class Downloader extends java.net.Authenticator
|
||||
{
|
||||
protected java.net.PasswordAuthentication getPasswordAuthentication()
|
||||
{
|
||||
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
|
||||
}
|
||||
public static void main( String[] args ) throws Exception
|
||||
{
|
||||
setDefault( new Downloader() );
|
||||
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
|
||||
}
|
||||
}
|
||||
END
|
||||
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
|
||||
verbose " - Compiling Downloader.java ..."
|
||||
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
|
||||
verbose " - Running Downloader.java ..."
|
||||
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
|
||||
fi
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
||||
if [ -n "${distributionSha256Sum-}" ]; then
|
||||
distributionSha256Result=false
|
||||
if [ "$MVN_CMD" = mvnd.sh ]; then
|
||||
echo "Checksum validation is not supported for maven-mvnd." >&2
|
||||
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||
exit 1
|
||||
elif command -v sha256sum >/dev/null; then
|
||||
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
|
||||
distributionSha256Result=true
|
||||
fi
|
||||
elif command -v shasum >/dev/null; then
|
||||
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
|
||||
distributionSha256Result=true
|
||||
fi
|
||||
else
|
||||
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
|
||||
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ $distributionSha256Result = false ]; then
|
||||
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
|
||||
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# unzip and move
|
||||
if command -v unzip >/dev/null; then
|
||||
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
|
||||
else
|
||||
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
|
||||
fi
|
||||
|
||||
# Find the actual extracted directory name (handles snapshots where filename != directory name)
|
||||
actualDistributionDir=""
|
||||
|
||||
# First try the expected directory name (for regular distributions)
|
||||
if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
|
||||
if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
|
||||
actualDistributionDir="$distributionUrlNameMain"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If not found, search for any directory with the Maven executable (for snapshots)
|
||||
if [ -z "$actualDistributionDir" ]; then
|
||||
# enable globbing to iterate over items
|
||||
set +f
|
||||
for dir in "$TMP_DOWNLOAD_DIR"/*; do
|
||||
if [ -d "$dir" ]; then
|
||||
if [ -f "$dir/bin/$MVN_CMD" ]; then
|
||||
actualDistributionDir="$(basename "$dir")"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
set -f
|
||||
fi
|
||||
|
||||
if [ -z "$actualDistributionDir" ]; then
|
||||
verbose "Contents of $TMP_DOWNLOAD_DIR:"
|
||||
verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
|
||||
die "Could not find Maven distribution directory in extracted archive"
|
||||
fi
|
||||
|
||||
verbose "Found extracted Maven distribution directory: $actualDistributionDir"
|
||||
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
|
||||
mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
|
||||
|
||||
clean || :
|
||||
exec_maven "$@"
|
||||
189
idp/backend/idp-starter/mvnw.cmd
vendored
Normal file
189
idp/backend/idp-starter/mvnw.cmd
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
<# : batch portion
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Apache Maven Wrapper startup batch script, version 3.3.4
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM MVNW_REPOURL - repo url base for downloading maven distribution
|
||||
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
|
||||
@SET __MVNW_CMD__=
|
||||
@SET __MVNW_ERROR__=
|
||||
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
|
||||
@SET PSModulePath=
|
||||
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
|
||||
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
|
||||
)
|
||||
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
|
||||
@SET __MVNW_PSMODULEP_SAVE=
|
||||
@SET __MVNW_ARG0_NAME__=
|
||||
@SET MVNW_USERNAME=
|
||||
@SET MVNW_PASSWORD=
|
||||
@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
|
||||
@echo Cannot start maven from wrapper >&2 && exit /b 1
|
||||
@GOTO :EOF
|
||||
: end batch / begin powershell #>
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
if ($env:MVNW_VERBOSE -eq "true") {
|
||||
$VerbosePreference = "Continue"
|
||||
}
|
||||
|
||||
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
|
||||
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
|
||||
if (!$distributionUrl) {
|
||||
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
|
||||
}
|
||||
|
||||
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
|
||||
"maven-mvnd-*" {
|
||||
$USE_MVND = $true
|
||||
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
|
||||
$MVN_CMD = "mvnd.cmd"
|
||||
break
|
||||
}
|
||||
default {
|
||||
$USE_MVND = $false
|
||||
$MVN_CMD = $script -replace '^mvnw','mvn'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
||||
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
||||
if ($env:MVNW_REPOURL) {
|
||||
$MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
|
||||
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
|
||||
}
|
||||
$distributionUrlName = $distributionUrl -replace '^.*/',''
|
||||
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
|
||||
|
||||
$MAVEN_M2_PATH = "$HOME/.m2"
|
||||
if ($env:MAVEN_USER_HOME) {
|
||||
$MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
|
||||
}
|
||||
|
||||
if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
|
||||
New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
|
||||
}
|
||||
|
||||
$MAVEN_WRAPPER_DISTS = $null
|
||||
if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
|
||||
$MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
|
||||
} else {
|
||||
$MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
|
||||
}
|
||||
|
||||
$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
|
||||
$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
|
||||
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
|
||||
|
||||
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
|
||||
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
||||
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
||||
exit $?
|
||||
}
|
||||
|
||||
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
|
||||
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
|
||||
}
|
||||
|
||||
# prepare tmp dir
|
||||
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
|
||||
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
|
||||
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
|
||||
trap {
|
||||
if ($TMP_DOWNLOAD_DIR.Exists) {
|
||||
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
||||
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
||||
}
|
||||
}
|
||||
|
||||
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
|
||||
|
||||
# Download and Install Apache Maven
|
||||
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
||||
Write-Verbose "Downloading from: $distributionUrl"
|
||||
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||
|
||||
$webclient = New-Object System.Net.WebClient
|
||||
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
|
||||
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
|
||||
}
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
||||
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
|
||||
if ($distributionSha256Sum) {
|
||||
if ($USE_MVND) {
|
||||
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
|
||||
}
|
||||
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
|
||||
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
|
||||
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
|
||||
}
|
||||
}
|
||||
|
||||
# unzip and move
|
||||
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
|
||||
|
||||
# Find the actual extracted directory name (handles snapshots where filename != directory name)
|
||||
$actualDistributionDir = ""
|
||||
|
||||
# First try the expected directory name (for regular distributions)
|
||||
$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
|
||||
$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
|
||||
if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
|
||||
$actualDistributionDir = $distributionUrlNameMain
|
||||
}
|
||||
|
||||
# If not found, search for any directory with the Maven executable (for snapshots)
|
||||
if (!$actualDistributionDir) {
|
||||
Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
|
||||
$testPath = Join-Path $_.FullName "bin/$MVN_CMD"
|
||||
if (Test-Path -Path $testPath -PathType Leaf) {
|
||||
$actualDistributionDir = $_.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$actualDistributionDir) {
|
||||
Write-Error "Could not find Maven distribution directory in extracted archive"
|
||||
}
|
||||
|
||||
Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
|
||||
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
|
||||
try {
|
||||
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
|
||||
} catch {
|
||||
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
|
||||
Write-Error "fail to move MAVEN_HOME"
|
||||
}
|
||||
} finally {
|
||||
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
||||
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
||||
}
|
||||
|
||||
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
||||
168
idp/backend/idp-starter/pom.xml
Normal file
168
idp/backend/idp-starter/pom.xml
Normal file
@@ -0,0 +1,168 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.5.10</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>org.lingniu</groupId>
|
||||
<artifactId>idp-starter</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>idp-starter</name>
|
||||
<description>idp-starter</description>
|
||||
<url/>
|
||||
<licenses>
|
||||
<license/>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer/>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection/>
|
||||
<developerConnection/>
|
||||
<tag/>
|
||||
<url/>
|
||||
</scm>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<spring-security-oauth2.version>1.5.5</spring-security-oauth2.version>
|
||||
<mysql.version>8.0.33</mysql.version>
|
||||
<mybatis-plus.version>3.5.10</mybatis-plus.version>
|
||||
<hutool.version>5.8.40</hutool.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-oauth2-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Tools -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.19.4</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.19.4</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.20.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
<version>2.0.60</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>pro.fessional</groupId>
|
||||
<artifactId>kaptcha</artifactId>
|
||||
<version>2.3.3</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>nl.basjes.parse.useragent</groupId>
|
||||
<artifactId>yauaa</artifactId>
|
||||
<version>7.32.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.nimbusds</groupId>
|
||||
<artifactId>nimbus-jose-jwt</artifactId>
|
||||
<version>10.0.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.lingniu.idp;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("org.lingniu.**.mapper")
|
||||
public class IdpStarterApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(IdpStarterApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.lingniu.idp.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 匿名访问不鉴权注解
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Anonymous
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.lingniu.idp.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 数据权限过滤注解
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface DataScope
|
||||
{
|
||||
/**
|
||||
* 部门表的别名
|
||||
*/
|
||||
public String deptAlias() default "";
|
||||
|
||||
/**
|
||||
* 用户表的别名
|
||||
*/
|
||||
public String userAlias() default "";
|
||||
|
||||
/**
|
||||
* 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
|
||||
*/
|
||||
public String permission() default "";
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.lingniu.idp.annotation;
|
||||
|
||||
import org.lingniu.idp.enums.DataSourceType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义多数据源切换注解
|
||||
*
|
||||
* 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface DataSource
|
||||
{
|
||||
/**
|
||||
* 切换数据源名称
|
||||
*/
|
||||
public DataSourceType value() default DataSourceType.MASTER;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.lingniu.idp.annotation;
|
||||
|
||||
import org.lingniu.idp.enums.BusinessType;
|
||||
import org.lingniu.idp.enums.OperatorType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义操作日志记录注解
|
||||
*
|
||||
* @author portal
|
||||
*
|
||||
*/
|
||||
@Target({ ElementType.PARAMETER, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Log
|
||||
{
|
||||
/**
|
||||
* 模块
|
||||
*/
|
||||
public String title() default "";
|
||||
|
||||
/**
|
||||
* 功能
|
||||
*/
|
||||
public BusinessType businessType() default BusinessType.OTHER;
|
||||
|
||||
/**
|
||||
* 操作人类别
|
||||
*/
|
||||
public OperatorType operatorType() default OperatorType.MANAGE;
|
||||
|
||||
/**
|
||||
* 是否保存请求的参数
|
||||
*/
|
||||
public boolean isSaveRequestData() default true;
|
||||
|
||||
/**
|
||||
* 是否保存响应的参数
|
||||
*/
|
||||
public boolean isSaveResponseData() default true;
|
||||
|
||||
/**
|
||||
* 排除指定的请求参数
|
||||
*/
|
||||
public String[] excludeParamNames() default {};
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.lingniu.idp.annotation;
|
||||
|
||||
import org.lingniu.idp.constant.CacheConstants;
|
||||
import org.lingniu.idp.enums.LimitType;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 限流注解
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface RateLimiter
|
||||
{
|
||||
/**
|
||||
* 限流key
|
||||
*/
|
||||
public String key() default CacheConstants.RATE_LIMIT_KEY;
|
||||
|
||||
/**
|
||||
* 限流时间,单位秒
|
||||
*/
|
||||
public int time() default 60;
|
||||
|
||||
/**
|
||||
* 限流次数
|
||||
*/
|
||||
public int count() default 100;
|
||||
|
||||
/**
|
||||
* 限流类型
|
||||
*/
|
||||
public LimitType limitType() default LimitType.DEFAULT;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.lingniu.idp.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义注解防止表单重复提交
|
||||
*
|
||||
* @author portal
|
||||
*
|
||||
*/
|
||||
@Inherited
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface RepeatSubmit
|
||||
{
|
||||
/**
|
||||
* 间隔时间(ms),小于此时间视为重复提交
|
||||
*/
|
||||
public int interval() default 5000;
|
||||
|
||||
/**
|
||||
* 提示消息
|
||||
*/
|
||||
public String message() default "不允许重复提交,请稍候再试";
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.lingniu.idp.annotation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import org.lingniu.idp.config.serializer.SensitiveJsonSerializer;
|
||||
import org.lingniu.idp.enums.DesensitizedType;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 数据脱敏注解
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@JacksonAnnotationsInside
|
||||
@JsonSerialize(using = SensitiveJsonSerializer.class)
|
||||
public @interface Sensitive
|
||||
{
|
||||
DesensitizedType desensitizedType();
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
package org.lingniu.idp.common.redis;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* spring redis 工具类
|
||||
*
|
||||
* @author portal
|
||||
**/
|
||||
@SuppressWarnings(value = { "unchecked", "rawtypes" })
|
||||
@Component
|
||||
public class RedisCache
|
||||
{
|
||||
@Autowired
|
||||
public RedisTemplate redisTemplate;
|
||||
|
||||
/**
|
||||
* 缓存基本的对象,Integer、String、实体类等
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @param value 缓存的值
|
||||
*/
|
||||
public <T> void setCacheObject(final String key, final T value)
|
||||
{
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存基本的对象,Integer、String、实体类等
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @param value 缓存的值
|
||||
* @param timeout 时间
|
||||
* @param timeUnit 时间颗粒度
|
||||
*/
|
||||
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
|
||||
{
|
||||
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置有效时间
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param timeout 超时时间
|
||||
* @return true=设置成功;false=设置失败
|
||||
*/
|
||||
public boolean expire(final String key, final long timeout)
|
||||
{
|
||||
return expire(key, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置有效时间
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param timeout 超时时间
|
||||
* @param unit 时间单位
|
||||
* @return true=设置成功;false=设置失败
|
||||
*/
|
||||
public boolean expire(final String key, final long timeout, final TimeUnit unit)
|
||||
{
|
||||
return redisTemplate.expire(key, timeout, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取有效时间
|
||||
*
|
||||
* @param key Redis键
|
||||
* @return 有效时间
|
||||
*/
|
||||
public long getExpire(final String key)
|
||||
{
|
||||
return redisTemplate.getExpire(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断 key是否存在
|
||||
*
|
||||
* @param key 键
|
||||
* @return true 存在 false不存在
|
||||
*/
|
||||
public Boolean hasKey(String key)
|
||||
{
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的基本对象。
|
||||
*
|
||||
* @param key 缓存键值
|
||||
* @return 缓存键值对应的数据
|
||||
*/
|
||||
public <T> T getCacheObject(final String key)
|
||||
{
|
||||
ValueOperations<String, T> operation = redisTemplate.opsForValue();
|
||||
return operation.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单个对象
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public boolean deleteObject(final String key)
|
||||
{
|
||||
return redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除集合对象
|
||||
*
|
||||
* @param collection 多个对象
|
||||
* @return
|
||||
*/
|
||||
public boolean deleteObject(final Collection collection)
|
||||
{
|
||||
return redisTemplate.delete(collection) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存List数据
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @param dataList 待缓存的List数据
|
||||
* @return 缓存的对象
|
||||
*/
|
||||
public <T> long setCacheList(final String key, final List<T> dataList)
|
||||
{
|
||||
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
|
||||
return count == null ? 0 : count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的list对象
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @return 缓存键值对应的数据
|
||||
*/
|
||||
public <T> List<T> getCacheList(final String key)
|
||||
{
|
||||
return redisTemplate.opsForList().range(key, 0, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存Set
|
||||
*
|
||||
* @param key 缓存键值
|
||||
* @param dataSet 缓存的数据
|
||||
* @return 缓存数据的对象
|
||||
*/
|
||||
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
|
||||
{
|
||||
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
|
||||
Iterator<T> it = dataSet.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
setOperation.add(it.next());
|
||||
}
|
||||
return setOperation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的set
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public <T> Set<T> getCacheSet(final String key)
|
||||
{
|
||||
return redisTemplate.opsForSet().members(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存Map
|
||||
*
|
||||
* @param key
|
||||
* @param dataMap
|
||||
*/
|
||||
public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
|
||||
{
|
||||
if (dataMap != null) {
|
||||
redisTemplate.opsForHash().putAll(key, dataMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的Map
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public <T> Map<String, T> getCacheMap(final String key)
|
||||
{
|
||||
return redisTemplate.opsForHash().entries(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 往Hash中存入数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKey Hash键
|
||||
* @param value 值
|
||||
*/
|
||||
public <T> void setCacheMapValue(final String key, final String hKey, final T value)
|
||||
{
|
||||
redisTemplate.opsForHash().put(key, hKey, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Hash中的数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKey Hash键
|
||||
* @return Hash中的对象
|
||||
*/
|
||||
public <T> T getCacheMapValue(final String key, final String hKey)
|
||||
{
|
||||
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
|
||||
return opsForHash.get(key, hKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取多个Hash中的数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKeys Hash键集合
|
||||
* @return Hash对象集合
|
||||
*/
|
||||
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
|
||||
{
|
||||
return redisTemplate.opsForHash().multiGet(key, hKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除Hash中的某条数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKey Hash键
|
||||
* @return 是否成功
|
||||
*/
|
||||
public boolean deleteCacheMapValue(final String key, final String hKey)
|
||||
{
|
||||
return redisTemplate.opsForHash().delete(key, hKey) > 0;
|
||||
}
|
||||
public boolean deleteCacheSetValue(final String key, final String hKey)
|
||||
{
|
||||
return redisTemplate.opsForSet().remove(key, hKey) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的基本对象列表
|
||||
*
|
||||
* @param pattern 字符串前缀
|
||||
* @return 对象列表
|
||||
*/
|
||||
public Collection<String> keys(final String pattern)
|
||||
{
|
||||
return redisTemplate.keys(pattern);
|
||||
}
|
||||
|
||||
public void setCacheSet(String key, String value) {
|
||||
redisTemplate.opsForSet().add(key,value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.lingniu.idp.common.xss;
|
||||
|
||||
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 自定义xss校验注解
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
|
||||
@Constraint(validatedBy = { XssValidator.class })
|
||||
public @interface Xss
|
||||
{
|
||||
String message()
|
||||
|
||||
default "不允许任何脚本运行";
|
||||
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.lingniu.idp.common.xss;
|
||||
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import org.lingniu.idp.utils.StringUtils;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 自定义xss校验注解实现
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class XssValidator implements ConstraintValidator<Xss, String>
|
||||
{
|
||||
private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";
|
||||
|
||||
@Override
|
||||
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext)
|
||||
{
|
||||
if (StringUtils.isBlank(value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return !containsHtml(value);
|
||||
}
|
||||
|
||||
public static boolean containsHtml(String value)
|
||||
{
|
||||
StringBuilder sHtml = new StringBuilder();
|
||||
Pattern pattern = Pattern.compile(HTML_PATTERN);
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
while (matcher.find())
|
||||
{
|
||||
sHtml.append(matcher.group());
|
||||
}
|
||||
return pattern.matcher(sHtml).matches();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.RSAKey;
|
||||
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
|
||||
import com.nimbusds.jose.jwk.source.JWKSource;
|
||||
import com.nimbusds.jose.proc.SecurityContext;
|
||||
import org.lingniu.idp.enums.CustomScopes;
|
||||
import org.lingniu.idp.security.filter.IdpAuthenticationFilter;
|
||||
import org.lingniu.idp.security.granttype.SmsCodeGrantType;
|
||||
import org.lingniu.idp.security.handler.Oauth2CodeSuccessHandler;
|
||||
import org.lingniu.idp.service.core.UserDetailsServiceImpl;
|
||||
import org.lingniu.idp.service.core.login.IdpTokenService;
|
||||
import org.lingniu.idp.service.core.login.LoginService;
|
||||
import org.lingniu.idp.service.core.login.RedisAccessTokenService;
|
||||
import org.lingniu.idp.utils.jwt.Jwks;
|
||||
import org.lingniu.idp.utils.jwt.JwtUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
|
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
|
||||
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
|
||||
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcUserInfoAuthenticationContext;
|
||||
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
|
||||
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer.authorizationServer;
|
||||
|
||||
@Configuration
|
||||
public class AuthorizationServerConfig {
|
||||
|
||||
// @Autowired
|
||||
// private SmsCodeAuthenticationProvider smsCodeAuthenticationProvider;
|
||||
private static final String CUSTOM_CONSENT_PAGE_URI = "http://localhost/oauth2/consent";
|
||||
@Autowired
|
||||
private JwtUtil jwtUtil;
|
||||
@Autowired
|
||||
private IdpTokenService idpTokenService;
|
||||
@Autowired
|
||||
private UserDetailsServiceImpl userDetailsService;
|
||||
@Autowired
|
||||
private OidcUserInfoMapper oidcUserInfoMapper;
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
|
||||
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = authorizationServer();
|
||||
http
|
||||
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
|
||||
.with(authorizationServerConfigurer, (authorizationServer) ->
|
||||
authorizationServer
|
||||
.authorizationEndpoint(authorizationEndpoint ->
|
||||
authorizationEndpoint.consentPage(CUSTOM_CONSENT_PAGE_URI)
|
||||
.authorizationResponseHandler(new Oauth2CodeSuccessHandler())
|
||||
)
|
||||
.tokenEndpoint(oAuth2TokenEndpointConfigurer -> {})
|
||||
.oidc(Customizer.withDefaults())
|
||||
.oidc(oidcConfigurer ->
|
||||
oidcConfigurer.userInfoEndpoint(oidcUserInfoEndpointConfigurer ->
|
||||
oidcUserInfoEndpointConfigurer.userInfoMapper(oidcUserInfoMapper)
|
||||
)
|
||||
) // Enable OpenID Connect 1.0
|
||||
)
|
||||
.addFilterAfter(jwtAuthenticationFilter(), LogoutFilter.class)
|
||||
.oauth2ResourceServer(oauth2ResourceServer ->
|
||||
oauth2ResourceServer.jwt(Customizer.withDefaults()))
|
||||
.authorizeHttpRequests((authorize) ->
|
||||
authorize.anyRequest().authenticated()
|
||||
)
|
||||
// Redirect to the /login page when not authenticated from the authorization endpoint
|
||||
// NOTE: DefaultSecurityConfig is configured with formLogin.loginPage("/login")
|
||||
.exceptionHandling((exceptions) -> exceptions
|
||||
.defaultAuthenticationEntryPointFor(
|
||||
new LoginUrlAuthenticationEntryPoint("http://localhost/login"),
|
||||
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
|
||||
)
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
@Bean
|
||||
public JdbcRegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {
|
||||
RegisteredClient client = RegisteredClient.withId("68dc155a-1034-4cd8-91dc-fca206e2f6d3")
|
||||
.clientId("2c6f1d9ff78641c78d72a848")
|
||||
//l3X95am7RaX8-Uu9-5nDYmD9-OFU-8_GHmkfnKfaS_0
|
||||
.clientSecret("{bcrypt}$2a$10$JDoQUK5aWvYiZZDpgSC8k.qPGfqbYtXAF5H1IW/e2quGWA8Zr6ffq")
|
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
|
||||
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
|
||||
.authorizationGrantType(SmsCodeGrantType.SMS_CODE) // 添加自定义Grant Type
|
||||
.clientName("PORTAL")
|
||||
.redirectUri("http://localhost:81/callback")
|
||||
.scope(OidcScopes.OPENID)
|
||||
.scope(OidcScopes.PROFILE)
|
||||
.scope(CustomScopes.PERMS.name().toLowerCase())
|
||||
.tokenSettings(TokenSettings.builder().accessTokenTimeToLive(Duration.ofHours(12)).refreshTokenTimeToLive(Duration.ofDays(7)).build())
|
||||
.scope("message.read")
|
||||
.scope("message.write")
|
||||
.build();
|
||||
RegisteredClient demo = RegisteredClient.withId("c81008aa-b33f-4ebc-bba7-3c6d0eee23b9")
|
||||
.clientId("b55c88c20db94790a60a5075")
|
||||
//l3X95am7RaX8-Uu9-5nDYmD9-OFU-8_GHmkfnKfaS_0
|
||||
.clientSecret("{bcrypt}$2a$10$gLsAsObi5ffOddmkf5YchOtT3olfcAmSTt75X6H/mHBVYf8DXnIwi")
|
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
|
||||
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
|
||||
.authorizationGrantType(SmsCodeGrantType.SMS_CODE) // 添加自定义Grant Type
|
||||
.clientName("DEMO")
|
||||
.redirectUri("http://localhost:9506/oauth2/callback")
|
||||
.scope(OidcScopes.OPENID)
|
||||
.scope(OidcScopes.PROFILE)
|
||||
.scope(CustomScopes.PERMS.name().toLowerCase())
|
||||
.tokenSettings(TokenSettings.builder().accessTokenTimeToLive(Duration.ofHours(12)).refreshTokenTimeToLive(Duration.ofDays(7)).build())
|
||||
.scope("read")
|
||||
.scope("write")
|
||||
.build();
|
||||
// Save registered client's in db as if in-memory
|
||||
JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
|
||||
registeredClientRepository.save(client);
|
||||
registeredClientRepository.save(demo);
|
||||
return registeredClientRepository;
|
||||
}
|
||||
|
||||
// @Bean
|
||||
// public OAuth2TokenGenerator<?> tokenGenerator(CustomAccessTokenGenerator accessTokenGenerator,OAuth2RefreshTokenGenerator refreshTokenGenerator) {
|
||||
// CustomAccessTokenGenerator accessTokenGenerator = new CustomAccessTokenGenerator();
|
||||
// OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
|
||||
// return new DelegatingOAuth2TokenGenerator(
|
||||
// accessTokenGenerator, refreshTokenGenerator
|
||||
// );
|
||||
// }
|
||||
@Bean
|
||||
public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate) {
|
||||
return new JdbcOAuth2AuthorizationService(jdbcTemplate,registeredClientRepository(jdbcTemplate));
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义JWT认证过滤器
|
||||
*/
|
||||
@Bean
|
||||
public IdpAuthenticationFilter jwtAuthenticationFilter() {
|
||||
return new IdpAuthenticationFilter(idpTokenService,userDetailsService);
|
||||
}
|
||||
/**
|
||||
* 主JWK源,使用应用配置的RSA密钥
|
||||
*/
|
||||
@Bean
|
||||
public JWKSource<SecurityContext> jwkSource() {
|
||||
try {
|
||||
// 从JwtUtil中获取密钥
|
||||
RSAPublicKey publicKey = jwtUtil.getPublicKey();
|
||||
RSAPrivateKey privateKey = jwtUtil.getPrivateKey();
|
||||
|
||||
// 创建RSA JWK,包含私钥(用于签名)
|
||||
RSAKey rsaKey = Jwks.generateRsa(
|
||||
publicKey,
|
||||
privateKey,
|
||||
"idp" // 密钥ID
|
||||
);
|
||||
|
||||
JWKSet jwkSet = new JWKSet(rsaKey);
|
||||
|
||||
// 使用ImmutableJWKSet包装
|
||||
return new ImmutableJWKSet<>(jwkSet);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("初始化JWK源失败", e);
|
||||
}
|
||||
}
|
||||
@Bean
|
||||
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
|
||||
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
||||
import com.google.code.kaptcha.util.Config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import static com.google.code.kaptcha.Constants.*;
|
||||
|
||||
/**
|
||||
* 验证码配置
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Configuration
|
||||
public class CaptchaConfig
|
||||
{
|
||||
@Bean(name = "captchaProducer")
|
||||
public DefaultKaptcha getKaptchaBean()
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes");
|
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
|
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
|
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
|
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
|
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
|
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
|
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
|
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
|
||||
@Bean(name = "captchaProducerMath")
|
||||
public DefaultKaptcha getKaptchaBeanMath()
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty(KAPTCHA_BORDER, "yes");
|
||||
// 边框颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
|
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
|
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
|
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
|
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
|
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
|
||||
// 验证码文本生成器
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "org.lingniu.idp.config.KaptchaTextCreator");
|
||||
// 验证码文本字符间距 默认为2
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
|
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
|
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
|
||||
// 验证码噪点颜色 默认为Color.BLACK
|
||||
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
|
||||
// 干扰实现类
|
||||
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
|
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import org.lingniu.idp.constant.Constants;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
||||
|
||||
/**
|
||||
* 资源文件配置加载
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Configuration
|
||||
public class I18nConfig implements WebMvcConfigurer
|
||||
{
|
||||
@Bean
|
||||
public LocaleResolver localeResolver()
|
||||
{
|
||||
SessionLocaleResolver slr = new SessionLocaleResolver();
|
||||
// 默认语言
|
||||
slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
|
||||
return slr;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocaleChangeInterceptor localeChangeInterceptor()
|
||||
{
|
||||
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
|
||||
// 参数名
|
||||
lci.setParamName("lang");
|
||||
return lci;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry)
|
||||
{
|
||||
registry.addInterceptor(localeChangeInterceptor());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import java.time.Duration;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "idp.jwt")
|
||||
public class JwtProperties {
|
||||
|
||||
// 令牌配置
|
||||
private String header = "Authorization";
|
||||
private String prefix = "Bearer ";
|
||||
private Duration expiration = Duration.ofHours(1);
|
||||
private Duration refreshExpiration = Duration.ofDays(7);
|
||||
|
||||
// RSA 密钥配置(支持文件路径或直接内容)
|
||||
private RsaKey rsa = new RsaKey();
|
||||
|
||||
// RSA 密钥内部类
|
||||
@Setter
|
||||
@Getter
|
||||
public static class RsaKey {
|
||||
// Getter 和 Setter
|
||||
/**
|
||||
* 私钥路径或内容(用于签名)
|
||||
* 优先级:content > location
|
||||
*/
|
||||
private String privateKey;
|
||||
|
||||
/**
|
||||
* 公钥路径或内容(用于验证)
|
||||
* 优先级:content > location
|
||||
*/
|
||||
private String publicKey;
|
||||
|
||||
/**
|
||||
* 密钥算法,默认 RSA
|
||||
*/
|
||||
private String algorithm = "RSA";
|
||||
|
||||
/**
|
||||
* 密钥长度,默认 2048
|
||||
*/
|
||||
private int keySize = 2048;
|
||||
|
||||
}
|
||||
|
||||
// Getter 和 Setter(原有)
|
||||
public String getHeader() { return header; }
|
||||
public void setHeader(String header) { this.header = header; }
|
||||
|
||||
public String getPrefix() { return prefix; }
|
||||
public void setPrefix(String prefix) { this.prefix = prefix; }
|
||||
|
||||
public Duration getExpiration() { return expiration; }
|
||||
public void setExpiration(Duration expiration) { this.expiration = expiration; }
|
||||
|
||||
public Duration getRefreshExpiration() { return refreshExpiration; }
|
||||
public void setRefreshExpiration(Duration refreshExpiration) { this.refreshExpiration = refreshExpiration; }
|
||||
|
||||
// RSA 配置 Getter 和 Setter
|
||||
public RsaKey getRsa() { return rsa; }
|
||||
public void setRsa(RsaKey rsa) { this.rsa = rsa; }
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* 验证码文本生成器
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class KaptchaTextCreator extends DefaultTextCreator
|
||||
{
|
||||
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
|
||||
|
||||
@Override
|
||||
public String getText()
|
||||
{
|
||||
Integer result = 0;
|
||||
Random random = new Random();
|
||||
int x = random.nextInt(10);
|
||||
int y = random.nextInt(10);
|
||||
StringBuilder suChinese = new StringBuilder();
|
||||
int randomoperands = random.nextInt(3);
|
||||
if (randomoperands == 0)
|
||||
{
|
||||
result = x * y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("*");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
else if (randomoperands == 1)
|
||||
{
|
||||
if ((x != 0) && y % x == 0)
|
||||
{
|
||||
result = y / x;
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
suChinese.append("/");
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = x + y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("+");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x >= y)
|
||||
{
|
||||
result = x - y;
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
suChinese.append("-");
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = y - x;
|
||||
suChinese.append(CNUMBERS[y]);
|
||||
suChinese.append("-");
|
||||
suChinese.append(CNUMBERS[x]);
|
||||
}
|
||||
}
|
||||
suChinese.append("=?@" + result);
|
||||
return suChinese.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import org.lingniu.idp.enums.CustomScopes;
|
||||
import org.lingniu.idp.model.dto.LoginUser;
|
||||
import org.lingniu.idp.model.entity.SysUser;
|
||||
import org.lingniu.idp.service.core.SysPermissionService;
|
||||
import org.lingniu.idp.service.core.login.LoginService;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcScopes;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
import org.springframework.security.oauth2.core.oidc.StandardClaimNames;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
||||
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcUserInfoAuthenticationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Component
|
||||
public class OidcUserInfoMapper
|
||||
implements Function<OidcUserInfoAuthenticationContext, OidcUserInfo> {
|
||||
|
||||
private final LoginService loginService;
|
||||
|
||||
|
||||
// @formatter:off
|
||||
private static final List<String> EMAIL_CLAIMS = Arrays.asList(
|
||||
StandardClaimNames.EMAIL,
|
||||
StandardClaimNames.EMAIL_VERIFIED
|
||||
);
|
||||
private static final List<String> PHONE_CLAIMS = Arrays.asList(
|
||||
StandardClaimNames.PHONE_NUMBER,
|
||||
StandardClaimNames.PHONE_NUMBER_VERIFIED
|
||||
);
|
||||
private static final List<String> PROFILE_CLAIMS = Arrays.asList(
|
||||
StandardClaimNames.NAME,
|
||||
StandardClaimNames.FAMILY_NAME,
|
||||
StandardClaimNames.GIVEN_NAME,
|
||||
StandardClaimNames.MIDDLE_NAME,
|
||||
StandardClaimNames.NICKNAME,
|
||||
StandardClaimNames.PREFERRED_USERNAME,
|
||||
StandardClaimNames.PROFILE,
|
||||
StandardClaimNames.PICTURE,
|
||||
StandardClaimNames.WEBSITE,
|
||||
StandardClaimNames.GENDER,
|
||||
StandardClaimNames.BIRTHDATE,
|
||||
StandardClaimNames.ZONEINFO,
|
||||
StandardClaimNames.LOCALE,
|
||||
StandardClaimNames.UPDATED_AT
|
||||
);
|
||||
|
||||
public OidcUserInfoMapper(LoginService loginService) {this.loginService = loginService;}
|
||||
// @formatter:on
|
||||
|
||||
@Override
|
||||
public OidcUserInfo apply(OidcUserInfoAuthenticationContext authenticationContext) {
|
||||
OAuth2Authorization authorization = authenticationContext.getAuthorization();
|
||||
OidcIdToken idToken = authorization.getToken(OidcIdToken.class).getToken();
|
||||
OAuth2AccessToken accessToken = authenticationContext.getAccessToken();
|
||||
Map<String, Object> scopeRequestedClaims = getClaimsRequestedByScope(idToken.getClaims(),
|
||||
accessToken.getScopes());
|
||||
String userName = authorization.getPrincipalName();
|
||||
SysUser sysUser = loginService.getUserDetail(userName);
|
||||
scopeRequestedClaims.put("userId",sysUser.getUserId());
|
||||
scopeRequestedClaims.put("currentDeptId",sysUser.getDeptId());
|
||||
scopeRequestedClaims.put("username",sysUser.getUserName());
|
||||
scopeRequestedClaims.put("userDepts",sysUser.getDeptList());
|
||||
scopeRequestedClaims.put("userPosts",sysUser.getPosts());
|
||||
scopeRequestedClaims.put("nickName",sysUser.getNickName());
|
||||
scopeRequestedClaims.put("sex",sysUser.getSex());
|
||||
if(accessToken.getScopes().contains(CustomScopes.PERMS.name().toLowerCase())){
|
||||
Map<String, Object> permissionInfo = loginService.getPermissionInfo(sysUser);
|
||||
scopeRequestedClaims.putAll(permissionInfo);
|
||||
|
||||
}
|
||||
return new OidcUserInfo(scopeRequestedClaims);
|
||||
}
|
||||
|
||||
private static Map<String, Object> getClaimsRequestedByScope(Map<String, Object> claims,
|
||||
Set<String> requestedScopes) {
|
||||
Set<String> scopeRequestedClaimNames = new HashSet<>(32);
|
||||
scopeRequestedClaimNames.add(StandardClaimNames.SUB);
|
||||
|
||||
if (requestedScopes.contains(OidcScopes.ADDRESS)) {
|
||||
scopeRequestedClaimNames.add(StandardClaimNames.ADDRESS);
|
||||
}
|
||||
if (requestedScopes.contains(OidcScopes.EMAIL)) {
|
||||
scopeRequestedClaimNames.addAll(EMAIL_CLAIMS);
|
||||
}
|
||||
if (requestedScopes.contains(OidcScopes.PHONE)) {
|
||||
scopeRequestedClaimNames.addAll(PHONE_CLAIMS);
|
||||
}
|
||||
if (requestedScopes.contains(OidcScopes.PROFILE)) {
|
||||
scopeRequestedClaimNames.addAll(PROFILE_CLAIMS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Map<String, Object> requestedClaims = new HashMap<>(claims);
|
||||
requestedClaims.keySet().removeIf((claimName) -> !scopeRequestedClaimNames.contains(claimName));
|
||||
|
||||
return requestedClaims;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 读取项目相关配置
|
||||
*
|
||||
* @author q
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "project")
|
||||
public class ProjectConfig
|
||||
{
|
||||
/** 项目名称 */
|
||||
private String name;
|
||||
|
||||
/** 版本 */
|
||||
private String version;
|
||||
|
||||
/** 版权年份 */
|
||||
private String copyrightYear;
|
||||
|
||||
/** 上传路径 */
|
||||
@Getter
|
||||
private static String profile;
|
||||
|
||||
/** 获取地址开关 */
|
||||
@Getter
|
||||
private static boolean addressEnabled;
|
||||
|
||||
/** 验证码类型 */
|
||||
@Getter
|
||||
private static String captchaType;
|
||||
|
||||
public void setProfile(String profile)
|
||||
{
|
||||
ProjectConfig.profile = profile;
|
||||
}
|
||||
|
||||
public void setAddressEnabled(boolean addressEnabled)
|
||||
{
|
||||
ProjectConfig.addressEnabled = addressEnabled;
|
||||
}
|
||||
|
||||
public void setCaptchaType(String captchaType) {
|
||||
ProjectConfig.captchaType = captchaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入上传路径
|
||||
*/
|
||||
public static String getImportPath()
|
||||
{
|
||||
return getProfile() + "/import";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取头像上传路径
|
||||
*/
|
||||
public static String getAvatarPath()
|
||||
{
|
||||
return getProfile() + "/avatar";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载路径
|
||||
*/
|
||||
public static String getDownloadPath()
|
||||
{
|
||||
return getProfile() + "/download/";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传路径
|
||||
*/
|
||||
public static String getUploadPath()
|
||||
{
|
||||
return getProfile() + "/upload";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import org.lingniu.idp.config.serializer.FastJson2JsonRedisSerializer;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
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.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* redis配置
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class RedisConfig extends CachingConfigurerSupport
|
||||
{
|
||||
@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);
|
||||
|
||||
// 使用StringRedisSerializer来序列化和反序列化redis的key值
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setValueSerializer(serializer);
|
||||
|
||||
// Hash的key也采用StringRedisSerializer的序列化方式
|
||||
template.setHashKeySerializer(new StringRedisSerializer());
|
||||
template.setHashValueSerializer(serializer);
|
||||
|
||||
template.afterPropertiesSet();
|
||||
return template;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultRedisScript<Long> limitScript()
|
||||
{
|
||||
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
|
||||
redisScript.setScriptText(limitScriptText());
|
||||
redisScript.setResultType(Long.class);
|
||||
return redisScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* 限流脚本
|
||||
*/
|
||||
private String limitScriptText()
|
||||
{
|
||||
return "local key = KEYS[1]\n" +
|
||||
"local count = tonumber(ARGV[1])\n" +
|
||||
"local time = tonumber(ARGV[2])\n" +
|
||||
"local current = redis.call('get', key);\n" +
|
||||
"if current and tonumber(current) > count then\n" +
|
||||
" return tonumber(current);\n" +
|
||||
"end\n" +
|
||||
"current = redis.call('incr', key)\n" +
|
||||
"if tonumber(current) == 1 then\n" +
|
||||
" redis.call('expire', key, time)\n" +
|
||||
"end\n" +
|
||||
"return tonumber(current);";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import org.lingniu.idp.security.filter.login.MobilePasswordAuthenticationFilter;
|
||||
import org.lingniu.idp.security.handler.AuthenticationEntryPointImpl;
|
||||
import org.lingniu.idp.security.handler.LoginSuccessHandler;
|
||||
import org.lingniu.idp.security.handler.LogoutSuccessHandlerImpl;
|
||||
import org.lingniu.idp.security.provider.MobilePasswordAuthenticationProvider;
|
||||
import org.lingniu.idp.security.provider.SmsCodeAuthenticationProvider;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
//@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
|
||||
|
||||
|
||||
private final AuthenticationEntryPointImpl unauthorizedHandler;
|
||||
private final LogoutSuccessHandlerImpl logoutSuccessHandler;
|
||||
private final MobilePasswordAuthenticationProvider mobilePasswordAuthenticationProvider;
|
||||
private final SmsCodeAuthenticationProvider smsCodeAuthenticationProvider;
|
||||
private final LoginSuccessHandler successHandler;
|
||||
|
||||
public SecurityConfig(AuthenticationEntryPointImpl unauthorizedHandler, LogoutSuccessHandlerImpl logoutSuccessHandler, MobilePasswordAuthenticationProvider mobilePasswordAuthenticationProvider, SmsCodeAuthenticationProvider smsCodeAuthenticationProvider, LoginSuccessHandler successHandler) {
|
||||
this.unauthorizedHandler = unauthorizedHandler;
|
||||
this.logoutSuccessHandler = logoutSuccessHandler;
|
||||
this.mobilePasswordAuthenticationProvider = mobilePasswordAuthenticationProvider;
|
||||
this.smsCodeAuthenticationProvider = smsCodeAuthenticationProvider;
|
||||
this.successHandler = successHandler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(2)
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
// 禁用HTTP响应标头
|
||||
.headers((headersCustomizer) -> {
|
||||
headersCustomizer.cacheControl(HeadersConfigurer.CacheControlConfig::disable).frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin);
|
||||
})
|
||||
// 认证失败处理类
|
||||
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
|
||||
// 基于token,所以不需要session
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.requestMatchers(
|
||||
"/api/login/**",
|
||||
"/captcha/image"
|
||||
).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
|
||||
// 添加Logout filter
|
||||
.logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
|
||||
.rememberMe(remember -> remember
|
||||
.tokenValiditySeconds(7 * 24 * 60 * 60) // 7天
|
||||
.key("remember-me-idp")
|
||||
);
|
||||
addFilters(http);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
private void addFilters(HttpSecurity http){
|
||||
MobilePasswordAuthenticationFilter mobilePasswordAuthenticationFilter = new MobilePasswordAuthenticationFilter(authenticationManager());
|
||||
mobilePasswordAuthenticationFilter.setAuthenticationSuccessHandler(successHandler);
|
||||
http.addFilterBefore(mobilePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
/**
|
||||
* 自定义JWT认证转换器
|
||||
*/
|
||||
@Bean
|
||||
public JwtAuthenticationConverter jwtAuthenticationConverter() {
|
||||
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
|
||||
grantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
|
||||
|
||||
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
|
||||
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
|
||||
|
||||
return jwtAuthenticationConverter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager() {
|
||||
List<AuthenticationProvider> providers = Arrays.asList(
|
||||
mobilePasswordAuthenticationProvider,
|
||||
smsCodeAuthenticationProvider
|
||||
);
|
||||
|
||||
return new ProviderManager(providers);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
|
||||
String portal = bCryptPasswordEncoder.encode("portal");
|
||||
System.out.println(portal);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.lingniu.idp.utils.Threads;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* 线程池配置
|
||||
*
|
||||
* @author portal
|
||||
**/
|
||||
@Configuration
|
||||
public class ThreadPoolConfig
|
||||
{
|
||||
// 核心线程池大小
|
||||
private int corePoolSize = 50;
|
||||
|
||||
// 最大可创建的线程数
|
||||
private int maxPoolSize = 200;
|
||||
|
||||
// 队列最大长度
|
||||
private int queueCapacity = 1000;
|
||||
|
||||
// 线程池维护线程所允许的空闲时间
|
||||
private int keepAliveSeconds = 300;
|
||||
|
||||
@Bean(name = "threadPoolTaskExecutor")
|
||||
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
|
||||
{
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setMaxPoolSize(maxPoolSize);
|
||||
executor.setCorePoolSize(corePoolSize);
|
||||
executor.setQueueCapacity(queueCapacity);
|
||||
executor.setKeepAliveSeconds(keepAliveSeconds);
|
||||
// 线程池对拒绝任务(无线程可用)的处理策略
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
return executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行周期性或定时任务
|
||||
*/
|
||||
@Bean(name = "scheduledExecutorService")
|
||||
protected ScheduledExecutorService scheduledExecutorService()
|
||||
{
|
||||
return new ScheduledThreadPoolExecutor(corePoolSize,
|
||||
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy())
|
||||
{
|
||||
@Override
|
||||
protected void afterExecute(Runnable r, Throwable t)
|
||||
{
|
||||
super.afterExecute(r, t);
|
||||
Threads.printException(r, t);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2020-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.lingniu.idp.config;
|
||||
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
|
||||
/**
|
||||
* @author Joe Grandja
|
||||
* @since 1.3
|
||||
*/
|
||||
@Profile("!test") // Exclude this from DemoAuthorizationServerApplicationTests and DemoAuthorizationServerConsentTests
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class TomcatServerConfig {
|
||||
|
||||
@Bean
|
||||
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> connectorCustomizer() {
|
||||
return (tomcat) -> tomcat.addAdditionalTomcatConnectors(createHttpConnector());
|
||||
}
|
||||
|
||||
private Connector createHttpConnector() {
|
||||
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
|
||||
connector.setScheme("http");
|
||||
connector.setPort(8000);
|
||||
connector.setSecure(false);
|
||||
connector.setRedirectPort(8443);
|
||||
return connector;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.lingniu.idp.config.serializer;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONReader;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.alibaba.fastjson2.filter.Filter;
|
||||
import org.lingniu.idp.constant.Constants;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.SerializationException;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Redis使用FastJson序列化
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
|
||||
{
|
||||
public static final Charset DEFAULT_CHARSET = Charset.forName("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 (bytes == null || bytes.length <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String str = new String(bytes, DEFAULT_CHARSET);
|
||||
|
||||
return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.lingniu.idp.config.serializer;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.BeanProperty;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
|
||||
import org.lingniu.idp.annotation.Sensitive;
|
||||
import org.lingniu.idp.model.dto.LoginUser;
|
||||
import org.lingniu.idp.enums.DesensitizedType;
|
||||
import org.lingniu.idp.utils.SecurityUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 数据脱敏序列化过滤
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
|
||||
{
|
||||
private DesensitizedType desensitizedType;
|
||||
|
||||
@Override
|
||||
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
|
||||
{
|
||||
if (desensitization())
|
||||
{
|
||||
gen.writeString(desensitizedType.desensitizer().apply(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
gen.writeString(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
|
||||
throws JsonMappingException
|
||||
{
|
||||
Sensitive annotation = property.getAnnotation(Sensitive.class);
|
||||
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
|
||||
{
|
||||
this.desensitizedType = annotation.desensitizedType();
|
||||
return this;
|
||||
}
|
||||
return prov.findValueSerializer(property.getType(), property);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否需要脱敏处理
|
||||
*/
|
||||
private boolean desensitization()
|
||||
{
|
||||
try
|
||||
{
|
||||
LoginUser securityUser = SecurityUtils.getLoginUser();
|
||||
// 管理员不脱敏
|
||||
return !securityUser.getUser().isAdmin();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.lingniu.idp.constant;
|
||||
|
||||
/**
|
||||
* 缓存的key 常量
|
||||
*
|
||||
*/
|
||||
public class CacheConstants
|
||||
{
|
||||
public static final String prefix = "idp_";
|
||||
/**
|
||||
* 登录用户 redis key
|
||||
*/
|
||||
public static final String LOGIN_TOKEN_KEY = prefix + "login_tokens:";
|
||||
|
||||
/**
|
||||
* 验证码 redis key
|
||||
*/
|
||||
public static final String CAPTCHA_CODE_KEY = prefix + "captcha_codes:";
|
||||
|
||||
/**
|
||||
* 参数管理 cache key
|
||||
*/
|
||||
public static final String SYS_CONFIG_KEY = prefix + "sys_config:";
|
||||
|
||||
/**
|
||||
* 字典管理 cache key
|
||||
*/
|
||||
public static final String SYS_DICT_KEY = prefix + "sys_dict:";
|
||||
|
||||
/**
|
||||
* 防重提交 redis key
|
||||
*/
|
||||
public static final String REPEAT_SUBMIT_KEY = prefix + "repeat_submit:";
|
||||
|
||||
/**
|
||||
* 限流 redis key
|
||||
*/
|
||||
public static final String RATE_LIMIT_KEY = prefix + "rate_limit:";
|
||||
|
||||
/**
|
||||
* 登录账户密码错误次数 redis key
|
||||
*/
|
||||
public static final String PWD_ERR_CNT_KEY = prefix + "pwd_err_cnt:";
|
||||
|
||||
// Access Token存储: String结构
|
||||
// 格式: access_token:{token}
|
||||
public static final String ACCESS_TOKEN_KEY = prefix + "access_token:%s";
|
||||
|
||||
// Refresh Token存储: Hash结构
|
||||
// 格式: refresh_token:{token}
|
||||
public static final String REFRESH_TOKEN_KEY = prefix + "refresh_token:%s";
|
||||
|
||||
// 用户会话管理
|
||||
public static final String USER_SESSIONS = prefix + "user_sessions:%s"; // userId -> session列表
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package org.lingniu.idp.constant;
|
||||
|
||||
import com.nimbusds.openid.connect.sdk.claims.ClaimType;
|
||||
import com.nimbusds.openid.connect.sdk.claims.CommonClaimsSet;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* 通用常量信息
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class Constants
|
||||
{
|
||||
/**
|
||||
* UTF-8 字符集
|
||||
*/
|
||||
public static final String UTF8 = "UTF-8";
|
||||
|
||||
/**
|
||||
* GBK 字符集
|
||||
*/
|
||||
public static final String GBK = "GBK";
|
||||
|
||||
/**
|
||||
* 系统语言
|
||||
*/
|
||||
public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
|
||||
|
||||
|
||||
/**
|
||||
* www主域
|
||||
*/
|
||||
public static final String WWW = "www.";
|
||||
|
||||
/**
|
||||
* http请求
|
||||
*/
|
||||
public static final String HTTP = "http://";
|
||||
|
||||
/**
|
||||
* https请求
|
||||
*/
|
||||
public static final String HTTPS = "https://";
|
||||
|
||||
/**
|
||||
* 通用成功标识
|
||||
*/
|
||||
public static final String SUCCESS = "0";
|
||||
|
||||
/**
|
||||
* 通用失败标识
|
||||
*/
|
||||
public static final String FAIL = "1";
|
||||
|
||||
/**
|
||||
* 登录成功
|
||||
*/
|
||||
public static final String LOGIN_SUCCESS = "Success";
|
||||
|
||||
/**
|
||||
* 注销
|
||||
*/
|
||||
public static final String LOGOUT = "Logout";
|
||||
|
||||
/**
|
||||
* 注册
|
||||
*/
|
||||
public static final String REGISTER = "Register";
|
||||
|
||||
/**
|
||||
* 登录失败
|
||||
*/
|
||||
public static final String LOGIN_FAIL = "Error";
|
||||
|
||||
/**
|
||||
* 所有权限标识
|
||||
*/
|
||||
public static final String ALL_PERMISSION = "*:*:*";
|
||||
|
||||
/**
|
||||
* 管理员角色权限标识
|
||||
*/
|
||||
public static final String SUPER_ADMIN = "admin";
|
||||
|
||||
/**
|
||||
* 角色权限分隔符
|
||||
*/
|
||||
public static final String ROLE_DELIMITER = ",";
|
||||
|
||||
/**
|
||||
* 权限标识分隔符
|
||||
*/
|
||||
public static final String PERMISSION_DELIMITER = ",";
|
||||
|
||||
/**
|
||||
* 验证码有效期(分钟)
|
||||
*/
|
||||
public static final Integer CAPTCHA_EXPIRATION = 2;
|
||||
|
||||
/**
|
||||
* 令牌
|
||||
*/
|
||||
public static final String TOKEN = "token";
|
||||
|
||||
/**
|
||||
* 令牌前缀
|
||||
*/
|
||||
public static final String TOKEN_PREFIX = "Bearer ";
|
||||
|
||||
/**
|
||||
* 令牌前缀
|
||||
*/
|
||||
public static final String LOGIN_USER_KEY = "login_user_key";
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
public static final String JWT_USERID = "userid";
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
public static final String JWT_USERNAME = CommonClaimsSet.SUB_CLAIM_NAME;
|
||||
|
||||
/**
|
||||
* 用户头像
|
||||
*/
|
||||
public static final String JWT_AVATAR = "avatar";
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
public static final String JWT_CREATED = "created";
|
||||
|
||||
/**
|
||||
* 用户权限
|
||||
*/
|
||||
public static final String JWT_AUTHORITIES = "authorities";
|
||||
|
||||
/**
|
||||
* 资源映射路径 前缀
|
||||
*/
|
||||
public static final String RESOURCE_PREFIX = "/profile";
|
||||
|
||||
/**
|
||||
* RMI 远程方法调用
|
||||
*/
|
||||
public static final String LOOKUP_RMI = "rmi:";
|
||||
|
||||
/**
|
||||
* LDAP 远程方法调用
|
||||
*/
|
||||
public static final String LOOKUP_LDAP = "ldap:";
|
||||
|
||||
/**
|
||||
* LDAPS 远程方法调用
|
||||
*/
|
||||
public static final String LOOKUP_LDAPS = "ldaps:";
|
||||
|
||||
/**
|
||||
* 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
|
||||
*/
|
||||
public static final String[] JSON_WHITELIST_STR = { "com.portal" };
|
||||
|
||||
/**
|
||||
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
||||
*/
|
||||
public static final String[] JOB_WHITELIST_STR = { "com.portal.quartz.task" };
|
||||
|
||||
/**
|
||||
* 定时任务违规的字符
|
||||
*/
|
||||
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
|
||||
"org.springframework", "org.apache", "org.lingniu.idp.utils.file", "org.lingniu.idp.config", "com.portal.generator" };
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package org.lingniu.idp.constant;
|
||||
|
||||
/**
|
||||
* 用户常量信息
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class UserConstants
|
||||
{
|
||||
/**
|
||||
* 平台内系统用户的唯一标志
|
||||
*/
|
||||
public static final String SYS_USER = "SYS_USER";
|
||||
|
||||
/** 正常状态 */
|
||||
public static final String NORMAL = "0";
|
||||
|
||||
/** 异常状态 */
|
||||
public static final String EXCEPTION = "1";
|
||||
|
||||
/** 用户封禁状态 */
|
||||
public static final String USER_DISABLE = "1";
|
||||
|
||||
/** 角色正常状态 */
|
||||
public static final String ROLE_NORMAL = "0";
|
||||
|
||||
/** 角色封禁状态 */
|
||||
public static final String ROLE_DISABLE = "1";
|
||||
|
||||
/** 部门正常状态 */
|
||||
public static final String DEPT_NORMAL = "0";
|
||||
|
||||
/** 部门停用状态 */
|
||||
public static final String DEPT_DISABLE = "1";
|
||||
|
||||
/** 字典正常状态 */
|
||||
public static final String DICT_NORMAL = "0";
|
||||
|
||||
/** 是否为系统默认(是) */
|
||||
public static final String YES = "Y";
|
||||
|
||||
/** 是否菜单外链(是) */
|
||||
public static final String YES_FRAME = "0";
|
||||
|
||||
/** 是否菜单外链(否) */
|
||||
public static final String NO_FRAME = "1";
|
||||
|
||||
/** 菜单类型(目录) */
|
||||
public static final String TYPE_DIR = "M";
|
||||
|
||||
/** 菜单类型(菜单) */
|
||||
public static final String TYPE_MENU = "C";
|
||||
|
||||
/** 菜单类型(按钮) */
|
||||
public static final String TYPE_BUTTON = "F";
|
||||
|
||||
/** Layout组件标识 */
|
||||
public final static String LAYOUT = "Layout";
|
||||
|
||||
/** ParentView组件标识 */
|
||||
public final static String PARENT_VIEW = "ParentView";
|
||||
|
||||
/** InnerLink组件标识 */
|
||||
public final static String INNER_LINK = "InnerLink";
|
||||
|
||||
/** 校验是否唯一的返回标识 */
|
||||
public final static boolean UNIQUE = true;
|
||||
public final static boolean NOT_UNIQUE = false;
|
||||
|
||||
/**
|
||||
* 用户名长度限制
|
||||
*/
|
||||
public static final int USERNAME_MIN_LENGTH = 2;
|
||||
public static final int USERNAME_MAX_LENGTH = 20;
|
||||
|
||||
/**
|
||||
* 密码长度限制
|
||||
*/
|
||||
public static final int PASSWORD_MIN_LENGTH = 5;
|
||||
public static final int PASSWORD_MAX_LENGTH = 20;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package org.lingniu.idp.controller;
|
||||
|
||||
import com.google.code.kaptcha.Producer;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.lingniu.idp.config.ProjectConfig;
|
||||
import org.lingniu.idp.constant.CacheConstants;
|
||||
import org.lingniu.idp.constant.Constants;
|
||||
import org.lingniu.idp.model.base.AjaxResult;
|
||||
import org.lingniu.idp.common.redis.RedisCache;
|
||||
import org.lingniu.idp.utils.sign.Base64;
|
||||
import org.lingniu.idp.utils.uuid.IdUtils;
|
||||
import org.lingniu.idp.service.ISysConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.FastByteArrayOutputStream;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 验证码操作处理
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/captcha")
|
||||
public class CaptchaController
|
||||
{
|
||||
@Resource(name = "captchaProducer")
|
||||
private Producer captchaProducer;
|
||||
|
||||
@Resource(name = "captchaProducerMath")
|
||||
private Producer captchaProducerMath;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Autowired
|
||||
private ISysConfigService configService;
|
||||
/**
|
||||
* 生成验证码
|
||||
*/
|
||||
@GetMapping("/image")
|
||||
public AjaxResult getCode(HttpServletResponse response) throws IOException
|
||||
{
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
boolean captchaEnabled = configService.selectCaptchaEnabled();
|
||||
ajax.put("captchaEnabled", captchaEnabled);
|
||||
if (!captchaEnabled)
|
||||
{
|
||||
return ajax;
|
||||
}
|
||||
|
||||
// 保存验证码信息
|
||||
String uuid = IdUtils.simpleUUID();
|
||||
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
|
||||
|
||||
String capStr = null, code = null;
|
||||
BufferedImage image = null;
|
||||
|
||||
// 生成验证码
|
||||
String captchaType = ProjectConfig.getCaptchaType();
|
||||
if ("math".equals(captchaType))
|
||||
{
|
||||
String capText = captchaProducerMath.createText();
|
||||
capStr = capText.substring(0, capText.lastIndexOf("@"));
|
||||
code = capText.substring(capText.lastIndexOf("@") + 1);
|
||||
image = captchaProducerMath.createImage(capStr);
|
||||
}
|
||||
else if ("char".equals(captchaType))
|
||||
{
|
||||
capStr = code = captchaProducer.createText();
|
||||
image = captchaProducer.createImage(capStr);
|
||||
}
|
||||
|
||||
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
|
||||
// 转换流信息写出
|
||||
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
ImageIO.write(image, "jpg", os);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
|
||||
ajax.put("uuid", uuid);
|
||||
ajax.put("img", Base64.encode(os.toByteArray()));
|
||||
return ajax;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.lingniu.idp.controller;
|
||||
|
||||
import org.lingniu.idp.model.base.AjaxResult;
|
||||
import org.lingniu.idp.model.entity.SysMenu;
|
||||
import org.lingniu.idp.model.entity.SysUser;
|
||||
import org.lingniu.idp.service.ISysMenuService;
|
||||
import org.lingniu.idp.service.ISysUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 登录验证
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/idp")
|
||||
public class SysLoginController
|
||||
{
|
||||
|
||||
@Autowired
|
||||
private ISysUserService sysUserService;
|
||||
@Autowired
|
||||
private ISysMenuService menuService;
|
||||
|
||||
|
||||
/**
|
||||
* 获取路由信息
|
||||
*
|
||||
* @return 路由信息
|
||||
*/
|
||||
@GetMapping("getRouters")
|
||||
public AjaxResult getRouters(@AuthenticationPrincipal Jwt jwt)
|
||||
{
|
||||
SysUser sysUser = sysUserService.selectUserByUserName(jwt.getSubject());
|
||||
List<SysMenu> menus = menuService.selectMenuTreeByUserId(sysUser.getUserId());
|
||||
return AjaxResult.success(menuService.buildMenus(menus));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
### 验证码
|
||||
# @no-redirect
|
||||
GET http://localhost:8000/captcha/image
|
||||
|
||||
### 密码登录 054aae95108e409dadc12af52f556a70
|
||||
# @no-redirect
|
||||
POST http://localhost:8000/api/login/account
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept: application/json
|
||||
|
||||
username=admin&password=admin123&uuid=1316459cfa7f40429bdc0f751229eb23&code=2
|
||||
|
||||
|
||||
##### e040b13e72e84086b63da369d60887e4
|
||||
POST http://localhost:8000/oauth2/authorize
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept: application/json
|
||||
Idp: 53c55ddb3caf44568ba429347fdad0e6
|
||||
Cookie: idp_refresh_token=7bb21a0dcac94aec99f08ae6a2d6db30
|
||||
|
||||
client_id=2c6f1d9ff78641c78d72a848&redirect_uri=http%3A%2F%2Flocalhost%3A81%2Fcallback&response_type=code&state=LXcbn1xobq6unvUCz5uwG7PcwtsNdbWg&scope=openid
|
||||
|
||||
### @name 一次性授权码登录
|
||||
POST http://localhost:8000/oauth2/token
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Basic MmM2ZjFkOWZmNzg2NDFjNzhkNzJhODQ4OmkxYnBlcjFKdzJnTGVUelVOMW9uaXd1SUNQRFFnTnVRRWNZeFRLSjVpdjA=
|
||||
|
||||
grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A81%2Fcallback&code=qmkNPAOk7pKTrTcHecwfSuona-O9Kjs-bbgSthovqSZz-wBhrqh9SUVeVUEN8ct4Gr7V-Dt4xMeupw3gFslSlbxZ8t2UHl74-63rGp7xnDVUGFWAA99TVa8hOnSgABZX&state=LXcbn1xobq6unvUCz5uwG7PcwtsNdbWg
|
||||
|
||||
|
||||
####
|
||||
GET http://localhost:8000/account/getInfo
|
||||
Authorization: Bearer eyJraWQiOiJpZHAiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IjJjNmYxZDlmZjc4NjQxYzc4ZDcyYTg0OCIsIm5iZiI6MTc3MDI1NTA3MiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDAwIiwiZXhwIjoxNzcwMjU4NjcyLCJpYXQiOjE3NzAyNTUwNzIsImp0aSI6IjVmNzAxM2EwLTU0MjctNDMyOC04ZTg0LWUwZjE0YjA4Y2IyYSJ9.KbradWCC1p6mD-JEd3IefUuzNvpNyUvGwyfuTRBVCC7jh-QGU36j4WxkeCtNJqaCBWZWQZVCJj068ysqanbRZRiSA4nADFMZnRVdBJD340TknKcGp7PbmiJfPD_uh4OzLosAu9xEUPjEW6q6rrjEqtIA9brK8NfP6A8A7aB8fYyKE0V1VO6j06AwC1CmXxUGrDgtJpU9_4NhV1Jf4cLBtECVG0pQDWMrEUNtrShPoa8gNJUUhP0gU0g-PyqBwlRhVl7Ra6T5lr4IIlsgK2D0Zu0ssFSJjZv_zhTW5Lo3xbe_DKVbWV4buJvLrHzlGBdFn7IV1-x6FwSZX10FBvXtOA
|
||||
###
|
||||
GET http://localhost:8000/.well-known/openid-configuration
|
||||
|
||||
|
||||
###
|
||||
GET http://localhost:8000/userinfo
|
||||
Authorization: Bearer eyJraWQiOiJpZHAiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IjJjNmYxZDlmZjc4NjQxYzc4ZDcyYTg0OCIsIm5iZiI6MTc3MDM2NTc1Nywic2NvcGUiOlsib3BlbmlkIl0sImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODAwMCIsImV4cCI6MTc3MDQwODk1NywiaWF0IjoxNzcwMzY1NzU3LCJqdGkiOiIwOWFjNDJjZi1jNmI4LTQ4MDMtOTkyMi0yMTYwMTk0Zjg1MzQifQ.TIrICdQ2iltZXS7PAGc1MHi_cHS9VuWgYsRZGI5t-ZoPjP1fvnkDg4OwO4In7vl1617-bUSlvl42Dm4AVZvtsnNWVVg6LXyf-Cge1kPENynnrpJzPRHkT5XwHno552UWwS6B3VtlSXsHnlK7D5BEZmsw4X5bL0fF56IPjoiaYjhgPoEp_Q9kU7b6d_2gnQAQeOst-K0yFtYtBIWl6QJX9q9Q-4maJdbuOAWqUOySTg2STKII3XYqK-r8sor4cv55itFqX4VZuhQuSQwbumLyJq55YYtl-vzYvST9zHRyeYxWaHVIhDZRNZR_AYkVB-Oj_8lASWRpDOSI10LJr4M1Qw
|
||||
|
||||
|
||||
###
|
||||
POST http://localhost:8000/oauth2/token
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Basic MmM2ZjFkOWZmNzg2NDFjNzhkNzJhODQ4OmkxYnBlcjFKdzJnTGVUelVOMW9uaXd1SUNQRFFnTnVRRWNZeFRLSjVpdjA=
|
||||
|
||||
grant_type=refresh_token&refresh_token=_NfU5Gdy_dANJkbvjJm6cK7PxNSHyQexWMY5KthA8Hs_nOFtPnTVChsHF-dmLjzhDRZk5nHNZWV7XhxyOp5qS-nLjScsrbvVwSmZhb20QpDLaSoUGtF-ZdBawvlceXks
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
/**
|
||||
* 操作状态
|
||||
*
|
||||
* @author portal
|
||||
*
|
||||
*/
|
||||
public enum BusinessStatus
|
||||
{
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
SUCCESS,
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
FAIL,
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
/**
|
||||
* 业务操作类型
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public enum BusinessType
|
||||
{
|
||||
/**
|
||||
* 其它
|
||||
*/
|
||||
OTHER,
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
INSERT,
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*/
|
||||
UPDATE,
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
DELETE,
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
GRANT,
|
||||
|
||||
/**
|
||||
* 导出
|
||||
*/
|
||||
EXPORT,
|
||||
|
||||
/**
|
||||
* 导入
|
||||
*/
|
||||
IMPORT,
|
||||
|
||||
/**
|
||||
* 强退
|
||||
*/
|
||||
FORCE,
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
*/
|
||||
GENCODE,
|
||||
|
||||
/**
|
||||
* 清空数据
|
||||
*/
|
||||
CLEAN,
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
public enum CustomScopes {
|
||||
PERMS
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
/**
|
||||
* 1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限
|
||||
*/
|
||||
public enum DataScope {
|
||||
ALL(1),
|
||||
CUSTOM(2),
|
||||
DEPT_AND_SUB(3),
|
||||
DEPT_SELF(4),
|
||||
USER_SELF(5);
|
||||
private Integer value;
|
||||
DataScope(Integer value){
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int value(){
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Integer value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
/**
|
||||
* 数据源
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public enum DataSourceType
|
||||
{
|
||||
/**
|
||||
* 主库
|
||||
*/
|
||||
MASTER,
|
||||
|
||||
/**
|
||||
* 从库
|
||||
*/
|
||||
SLAVE
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
import org.lingniu.idp.utils.DesensitizedUtil;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 脱敏类型
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public enum DesensitizedType
|
||||
{
|
||||
/**
|
||||
* 姓名,第2位星号替换
|
||||
*/
|
||||
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
|
||||
|
||||
/**
|
||||
* 密码,全部字符都用*代替
|
||||
*/
|
||||
PASSWORD(DesensitizedUtil::password),
|
||||
|
||||
/**
|
||||
* 身份证,中间10位星号替换
|
||||
*/
|
||||
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")),
|
||||
|
||||
/**
|
||||
* 手机号,中间4位星号替换
|
||||
*/
|
||||
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
|
||||
|
||||
/**
|
||||
* 电子邮箱,仅显示第一个字母和@后面的地址显示,其他星号替换
|
||||
*/
|
||||
EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
|
||||
|
||||
/**
|
||||
* 银行卡号,保留最后4位,其他星号替换
|
||||
*/
|
||||
BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
|
||||
|
||||
/**
|
||||
* 车牌号码,包含普通车辆、新能源车辆
|
||||
*/
|
||||
CAR_LICENSE(DesensitizedUtil::carLicense);
|
||||
|
||||
private final Function<String, String> desensitizer;
|
||||
|
||||
DesensitizedType(Function<String, String> desensitizer)
|
||||
{
|
||||
this.desensitizer = desensitizer;
|
||||
}
|
||||
|
||||
public Function<String, String> desensitizer()
|
||||
{
|
||||
return desensitizer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
/**
|
||||
* 设备类型枚举
|
||||
*/
|
||||
public enum DeviceType {
|
||||
WEB("网页"),
|
||||
IOS("iOS"),
|
||||
ANDROID("安卓"),
|
||||
H5("H5"),
|
||||
MINI_PROGRAM("小程序"),
|
||||
DESKTOP("桌面端"),
|
||||
OTHER("其他");
|
||||
|
||||
private final String description;
|
||||
|
||||
DeviceType(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 请求方式
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public enum HttpMethod
|
||||
{
|
||||
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
|
||||
|
||||
private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
|
||||
|
||||
static
|
||||
{
|
||||
for (HttpMethod httpMethod : values())
|
||||
{
|
||||
mappings.put(httpMethod.name(), httpMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static HttpMethod resolve(@Nullable String method)
|
||||
{
|
||||
return (method != null ? mappings.get(method) : null);
|
||||
}
|
||||
|
||||
public boolean matches(String method)
|
||||
{
|
||||
return (this == resolve(method));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
/**
|
||||
* 限流类型
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
|
||||
public enum LimitType
|
||||
{
|
||||
/**
|
||||
* 默认策略全局限流
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
/**
|
||||
* 根据请求者IP进行限流
|
||||
*/
|
||||
IP
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
/**
|
||||
* 操作人类别
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public enum OperatorType
|
||||
{
|
||||
/**
|
||||
* 其它
|
||||
*/
|
||||
OTHER,
|
||||
|
||||
/**
|
||||
* 后台用户
|
||||
*/
|
||||
MANAGE,
|
||||
|
||||
/**
|
||||
* 手机端用户
|
||||
*/
|
||||
MOBILE
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
/**
|
||||
* 撤销原因枚举
|
||||
*/
|
||||
public enum RevokeReason {
|
||||
USER_LOGOUT("用户主动登出"),
|
||||
ADMIN_REVOKED("管理员撤销"),
|
||||
DEVICE_CHANGED("设备变更"),
|
||||
SUSPICIOUS_ACTIVITY("可疑活动"),
|
||||
PASSWORD_CHANGED("密码修改"),
|
||||
SESSION_EXPIRED("会话过期"),
|
||||
SECURITY_POLICY("安全策略"),
|
||||
OTHER("其他");
|
||||
|
||||
private final String description;
|
||||
|
||||
RevokeReason(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.lingniu.idp.enums;
|
||||
|
||||
/**
|
||||
* 用户状态
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public enum UserStatus
|
||||
{
|
||||
OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
|
||||
|
||||
private final String code;
|
||||
private final String info;
|
||||
|
||||
UserStatus(String code, String info)
|
||||
{
|
||||
this.code = code;
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public String getCode()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getInfo()
|
||||
{
|
||||
return info;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.lingniu.idp.exception;
|
||||
|
||||
/**
|
||||
* 演示模式异常
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class DemoModeException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DemoModeException()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.lingniu.idp.exception;
|
||||
|
||||
/**
|
||||
* 全局异常
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class GlobalException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 错误提示
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 错误明细,内部调试错误
|
||||
*
|
||||
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
|
||||
*/
|
||||
private String detailMessage;
|
||||
|
||||
/**
|
||||
* 空构造方法,避免反序列化问题
|
||||
*/
|
||||
public GlobalException()
|
||||
{
|
||||
}
|
||||
|
||||
public GlobalException(String message)
|
||||
{
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getDetailMessage()
|
||||
{
|
||||
return detailMessage;
|
||||
}
|
||||
|
||||
public GlobalException setDetailMessage(String detailMessage)
|
||||
{
|
||||
this.detailMessage = detailMessage;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
public GlobalException setMessage(String message)
|
||||
{
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.lingniu.idp.exception;
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public final class ServiceException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 错误提示
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 错误明细,内部调试错误
|
||||
*
|
||||
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
|
||||
*/
|
||||
private String detailMessage;
|
||||
|
||||
/**
|
||||
* 空构造方法,避免反序列化问题
|
||||
*/
|
||||
public ServiceException()
|
||||
{
|
||||
}
|
||||
|
||||
public ServiceException(String message)
|
||||
{
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public ServiceException(String message, Integer code)
|
||||
{
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getDetailMessage()
|
||||
{
|
||||
return detailMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
public Integer getCode()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
public ServiceException setMessage(String message)
|
||||
{
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ServiceException setDetailMessage(String detailMessage)
|
||||
{
|
||||
this.detailMessage = detailMessage;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.lingniu.idp.exception;
|
||||
|
||||
/**
|
||||
* 工具类异常
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class UtilException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 8247610319171014183L;
|
||||
|
||||
public UtilException(Throwable e)
|
||||
{
|
||||
super(e.getMessage(), e);
|
||||
}
|
||||
|
||||
public UtilException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UtilException(String message, Throwable throwable)
|
||||
{
|
||||
super(message, throwable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package org.lingniu.idp.exception.base;
|
||||
|
||||
import org.lingniu.idp.utils.MessageUtils;
|
||||
import org.lingniu.idp.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 基础异常
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class BaseException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 所属模块
|
||||
*/
|
||||
private String module;
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 错误码对应的参数
|
||||
*/
|
||||
private Object[] args;
|
||||
|
||||
/**
|
||||
* 错误消息
|
||||
*/
|
||||
private String defaultMessage;
|
||||
|
||||
public BaseException(String module, String code, Object[] args, String defaultMessage)
|
||||
{
|
||||
this.module = module;
|
||||
this.code = code;
|
||||
this.args = args;
|
||||
this.defaultMessage = defaultMessage;
|
||||
}
|
||||
|
||||
public BaseException(String module, String code, Object[] args)
|
||||
{
|
||||
this(module, code, args, null);
|
||||
}
|
||||
|
||||
public BaseException(String module, String defaultMessage)
|
||||
{
|
||||
this(module, null, null, defaultMessage);
|
||||
}
|
||||
|
||||
public BaseException(String code, Object[] args)
|
||||
{
|
||||
this(null, code, args, null);
|
||||
}
|
||||
|
||||
public BaseException(String defaultMessage)
|
||||
{
|
||||
this(null, null, null, defaultMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
String message = null;
|
||||
if (!StringUtils.isEmpty(code))
|
||||
{
|
||||
message = MessageUtils.message(code, args);
|
||||
}
|
||||
if (message == null)
|
||||
{
|
||||
message = defaultMessage;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getModule()
|
||||
{
|
||||
return module;
|
||||
}
|
||||
|
||||
public String getCode()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
public Object[] getArgs()
|
||||
{
|
||||
return args;
|
||||
}
|
||||
|
||||
public String getDefaultMessage()
|
||||
{
|
||||
return defaultMessage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.lingniu.idp.exception.user;
|
||||
|
||||
import org.lingniu.idp.exception.user.UserException;
|
||||
|
||||
/**
|
||||
* 黑名单IP异常类
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class BlackListException extends UserException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public BlackListException()
|
||||
{
|
||||
super("login.blocked", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.lingniu.idp.exception.user;
|
||||
|
||||
import org.lingniu.idp.exception.user.UserException;
|
||||
|
||||
/**
|
||||
* 验证码错误异常类
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class CaptchaException extends UserException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CaptchaException()
|
||||
{
|
||||
super("user.jcaptcha.error", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.lingniu.idp.exception.user;
|
||||
|
||||
import org.lingniu.idp.exception.user.UserException;
|
||||
|
||||
/**
|
||||
* 验证码失效异常类
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class CaptchaExpireException extends UserException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CaptchaExpireException()
|
||||
{
|
||||
super("user.jcaptcha.expire", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.lingniu.idp.exception.user;
|
||||
|
||||
import org.lingniu.idp.exception.base.BaseException;
|
||||
|
||||
/**
|
||||
* 用户信息异常类
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class UserException extends BaseException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UserException(String code, Object[] args)
|
||||
{
|
||||
super("user", code, args, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.lingniu.idp.exception.user;
|
||||
|
||||
import org.lingniu.idp.exception.user.UserException;
|
||||
|
||||
/**
|
||||
* 用户不存在异常类
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class UserNotExistsException extends UserException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UserNotExistsException()
|
||||
{
|
||||
super("user.not.exists", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.lingniu.idp.exception.user;
|
||||
|
||||
import org.lingniu.idp.exception.user.UserException;
|
||||
|
||||
/**
|
||||
* 用户密码不正确或不符合规范异常类
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class UserPasswordNotMatchException extends UserException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UserPasswordNotMatchException()
|
||||
{
|
||||
super("user.password.not.match", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.lingniu.idp.exception.user;
|
||||
|
||||
/**
|
||||
* 用户错误最大次数异常类
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class UserPasswordRetryLimitExceedException extends UserException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime)
|
||||
{
|
||||
super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.lingniu.idp.manager;
|
||||
|
||||
import org.lingniu.idp.utils.Threads;
|
||||
import org.lingniu.idp.utils.spring.SpringUtils;
|
||||
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 异步任务管理器
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class AsyncManager
|
||||
{
|
||||
/**
|
||||
* 操作延迟10毫秒
|
||||
*/
|
||||
private final int OPERATE_DELAY_TIME = 10;
|
||||
|
||||
/**
|
||||
* 异步操作任务调度线程池
|
||||
*/
|
||||
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
|
||||
|
||||
/**
|
||||
* 单例模式
|
||||
*/
|
||||
private AsyncManager(){}
|
||||
|
||||
private static AsyncManager me = new AsyncManager();
|
||||
|
||||
public static AsyncManager me()
|
||||
{
|
||||
return me;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行任务
|
||||
*
|
||||
* @param task 任务
|
||||
*/
|
||||
public void execute(TimerTask task)
|
||||
{
|
||||
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止任务线程池
|
||||
*/
|
||||
public void shutdown()
|
||||
{
|
||||
Threads.shutdownAndAwaitTermination(executor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.lingniu.idp.manager;
|
||||
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* 确保应用退出时能关闭后台线程
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Component
|
||||
public class ShutdownManager
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger("sys-user");
|
||||
|
||||
@PreDestroy
|
||||
public void destroy()
|
||||
{
|
||||
shutdownAsyncManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止异步执行任务
|
||||
*/
|
||||
private void shutdownAsyncManager()
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.info("====关闭后台任务任务线程池====");
|
||||
AsyncManager.me().shutdown();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package org.lingniu.idp.manager.factory;
|
||||
import org.lingniu.idp.constant.Constants;
|
||||
import org.lingniu.idp.service.ISysLogininforService;
|
||||
import org.lingniu.idp.service.ISysOperLogService;
|
||||
import org.lingniu.idp.utils.LogUtils;
|
||||
import org.lingniu.idp.utils.ServletUtils;
|
||||
import org.lingniu.idp.utils.StringUtils;
|
||||
import org.lingniu.idp.utils.http.UserAgentUtils;
|
||||
import org.lingniu.idp.utils.ip.AddressUtils;
|
||||
import org.lingniu.idp.utils.ip.IpUtils;
|
||||
import org.lingniu.idp.utils.spring.SpringUtils;
|
||||
|
||||
import org.lingniu.idp.model.entity.SysLogininfor;
|
||||
import org.lingniu.idp.model.entity.SysOperLog;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* 异步工厂(产生任务用)
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class AsyncFactory
|
||||
{
|
||||
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param status 状态
|
||||
* @param message 消息
|
||||
* @param args 列表
|
||||
* @return 任务task
|
||||
*/
|
||||
public static TimerTask recordLogininfor(final String username, final String status, final String message,
|
||||
final Object... args)
|
||||
{
|
||||
final String userAgent = ServletUtils.getRequest().getHeader("User-Agent");
|
||||
final String ip = IpUtils.getIpAddr();
|
||||
return new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
String address = AddressUtils.getRealAddressByIP(ip);
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append(LogUtils.getBlock(ip));
|
||||
s.append(address);
|
||||
s.append(LogUtils.getBlock(username));
|
||||
s.append(LogUtils.getBlock(status));
|
||||
s.append(LogUtils.getBlock(message));
|
||||
// 打印信息到日志
|
||||
sys_user_logger.info(s.toString(), args);
|
||||
// 获取客户端操作系统
|
||||
String os = UserAgentUtils.getOperatingSystem(userAgent);
|
||||
// 获取客户端浏览器
|
||||
String browser = UserAgentUtils.getBrowser(userAgent);
|
||||
// 封装对象
|
||||
SysLogininfor logininfor = new SysLogininfor();
|
||||
logininfor.setUserName(username);
|
||||
logininfor.setIpaddr(ip);
|
||||
logininfor.setLoginLocation(address);
|
||||
logininfor.setBrowser(browser);
|
||||
logininfor.setOs(os);
|
||||
logininfor.setMsg(message);
|
||||
// 日志状态
|
||||
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
|
||||
{
|
||||
logininfor.setStatus(Constants.SUCCESS);
|
||||
}
|
||||
else if (Constants.LOGIN_FAIL.equals(status))
|
||||
{
|
||||
logininfor.setStatus(Constants.FAIL);
|
||||
}
|
||||
// 插入数据
|
||||
SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作日志记录
|
||||
*
|
||||
* @param operLog 操作日志信息
|
||||
* @return 任务task
|
||||
*/
|
||||
public static TimerTask recordOper(final SysOperLog operLog)
|
||||
{
|
||||
return new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
// 远程查询操作地点
|
||||
operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
|
||||
SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.lingniu.idp.model.entity.SysConfig;
|
||||
|
||||
/**
|
||||
* 参数配置 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysConfigMapper
|
||||
{
|
||||
/**
|
||||
* 查询参数配置信息
|
||||
*
|
||||
* @param config 参数配置信息
|
||||
* @return 参数配置信息
|
||||
*/
|
||||
public SysConfig selectConfig(SysConfig config);
|
||||
|
||||
/**
|
||||
* 通过ID查询配置
|
||||
*
|
||||
* @param configId 参数ID
|
||||
* @return 参数配置信息
|
||||
*/
|
||||
public SysConfig selectConfigById(Long configId);
|
||||
|
||||
/**
|
||||
* 查询参数配置列表
|
||||
*
|
||||
* @param config 参数配置信息
|
||||
* @return 参数配置集合
|
||||
*/
|
||||
public List<SysConfig> selectConfigList(SysConfig config);
|
||||
|
||||
/**
|
||||
* 根据键名查询参数配置信息
|
||||
*
|
||||
* @param configKey 参数键名
|
||||
* @return 参数配置信息
|
||||
*/
|
||||
public SysConfig checkConfigKeyUnique(String configKey);
|
||||
|
||||
/**
|
||||
* 新增参数配置
|
||||
*
|
||||
* @param config 参数配置信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertConfig(SysConfig config);
|
||||
|
||||
/**
|
||||
* 修改参数配置
|
||||
*
|
||||
* @param config 参数配置信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateConfig(SysConfig config);
|
||||
|
||||
/**
|
||||
* 删除参数配置
|
||||
*
|
||||
* @param configId 参数ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteConfigById(Long configId);
|
||||
|
||||
/**
|
||||
* 批量删除参数信息
|
||||
*
|
||||
* @param configIds 需要删除的参数ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteConfigByIds(Long[] configIds);
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.lingniu.idp.model.entity.SysDept;
|
||||
|
||||
/**
|
||||
* 部门管理 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysDeptMapper
|
||||
{
|
||||
/**
|
||||
* 查询部门管理数据
|
||||
*
|
||||
* @param dept 部门信息
|
||||
* @return 部门信息集合
|
||||
*/
|
||||
public List<SysDept> selectDeptList(SysDept dept);
|
||||
|
||||
/**
|
||||
* 根据角色ID查询部门树信息
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param deptCheckStrictly 部门树选择项是否关联显示
|
||||
* @return 选中部门列表
|
||||
*/
|
||||
public List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
|
||||
|
||||
/**
|
||||
* 根据部门ID查询信息
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return 部门信息
|
||||
*/
|
||||
public SysDept selectDeptById(Long deptId);
|
||||
public List<SysDept> selectDeptListByUserRole(Long userId);
|
||||
|
||||
/**
|
||||
* 根据ID查询所有子部门
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return 部门列表
|
||||
*/
|
||||
public List<SysDept> selectChildrenDeptById(Long deptId);
|
||||
|
||||
/**
|
||||
* 根据ID查询所有子部门(正常状态)
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return 子部门数
|
||||
*/
|
||||
public int selectNormalChildrenDeptById(Long deptId);
|
||||
|
||||
/**
|
||||
* 是否存在子节点
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int hasChildByDeptId(Long deptId);
|
||||
|
||||
/**
|
||||
* 查询部门是否存在用户
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int checkDeptExistUser(Long deptId);
|
||||
|
||||
/**
|
||||
* 校验部门名称是否唯一
|
||||
*
|
||||
* @param deptName 部门名称
|
||||
* @param parentId 父部门ID
|
||||
* @return 结果
|
||||
*/
|
||||
public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId);
|
||||
|
||||
/**
|
||||
* 新增部门信息
|
||||
*
|
||||
* @param dept 部门信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertDept(SysDept dept);
|
||||
|
||||
/**
|
||||
* 修改部门信息
|
||||
*
|
||||
* @param dept 部门信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateDept(SysDept dept);
|
||||
|
||||
/**
|
||||
* 修改所在部门正常状态
|
||||
*
|
||||
* @param deptIds 部门ID组
|
||||
*/
|
||||
public void updateDeptStatusNormal(Long[] deptIds);
|
||||
|
||||
/**
|
||||
* 修改子元素关系
|
||||
*
|
||||
* @param depts 子元素
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateDeptChildren(@Param("depts") List<SysDept> depts);
|
||||
|
||||
/**
|
||||
* 删除部门管理信息
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteDeptById(Long deptId);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.lingniu.idp.model.entity.SysLogininfor;
|
||||
|
||||
/**
|
||||
* 系统访问日志情况信息 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysLogininforMapper
|
||||
{
|
||||
/**
|
||||
* 新增系统登录日志
|
||||
*
|
||||
* @param logininfor 访问日志对象
|
||||
*/
|
||||
public void insertLogininfor(SysLogininfor logininfor);
|
||||
|
||||
/**
|
||||
* 查询系统登录日志集合
|
||||
*
|
||||
* @param logininfor 访问日志对象
|
||||
* @return 登录记录集合
|
||||
*/
|
||||
public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
|
||||
|
||||
/**
|
||||
* 批量删除系统登录日志
|
||||
*
|
||||
* @param infoIds 需要删除的登录日志ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteLogininforByIds(Long[] infoIds);
|
||||
|
||||
/**
|
||||
* 清空系统登录日志
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public int cleanLogininfor();
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.lingniu.idp.model.entity.SysMenu;
|
||||
|
||||
/**
|
||||
* 菜单表 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysMenuMapper
|
||||
{
|
||||
/**
|
||||
* 查询系统菜单列表
|
||||
*
|
||||
* @param menu 菜单信息
|
||||
* @return 菜单列表
|
||||
*/
|
||||
public List<SysMenu> selectMenuList(SysMenu menu);
|
||||
|
||||
/**
|
||||
* 根据用户所有权限
|
||||
*
|
||||
* @return 权限列表
|
||||
*/
|
||||
public List<String> selectMenuPerms();
|
||||
|
||||
/**
|
||||
* 根据用户查询系统菜单列表
|
||||
*
|
||||
* @param menu 菜单信息
|
||||
* @return 菜单列表
|
||||
*/
|
||||
public List<SysMenu> selectMenuListByUserId(SysMenu menu);
|
||||
|
||||
/**
|
||||
* 根据角色ID查询权限
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @return 权限列表
|
||||
*/
|
||||
public List<String> selectMenuPermsByRoleId(Long roleId);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询权限
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 权限列表
|
||||
*/
|
||||
public List<String> selectMenuPermsByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询菜单
|
||||
*
|
||||
* @return 菜单列表
|
||||
*/
|
||||
public List<SysMenu> selectMenuTreeAll();
|
||||
|
||||
/**
|
||||
* 根据用户ID查询菜单
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 菜单列表
|
||||
*/
|
||||
public List<SysMenu> selectMenuTreeByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 根据角色ID查询菜单树信息
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param menuCheckStrictly 菜单树选择项是否关联显示
|
||||
* @return 选中菜单列表
|
||||
*/
|
||||
public List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
|
||||
|
||||
/**
|
||||
* 根据菜单ID查询信息
|
||||
*
|
||||
* @param menuId 菜单ID
|
||||
* @return 菜单信息
|
||||
*/
|
||||
public SysMenu selectMenuById(Long menuId);
|
||||
|
||||
/**
|
||||
* 是否存在菜单子节点
|
||||
*
|
||||
* @param menuId 菜单ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int hasChildByMenuId(Long menuId);
|
||||
|
||||
/**
|
||||
* 新增菜单信息
|
||||
*
|
||||
* @param menu 菜单信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertMenu(SysMenu menu);
|
||||
|
||||
/**
|
||||
* 修改菜单信息
|
||||
*
|
||||
* @param menu 菜单信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateMenu(SysMenu menu);
|
||||
|
||||
/**
|
||||
* 删除菜单管理信息
|
||||
*
|
||||
* @param menuId 菜单ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteMenuById(Long menuId);
|
||||
|
||||
/**
|
||||
* 校验菜单名称是否唯一
|
||||
*
|
||||
* @param menuName 菜单名称
|
||||
* @param parentId 父菜单ID
|
||||
* @return 结果
|
||||
*/
|
||||
public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.lingniu.idp.model.entity.SysOperLog;
|
||||
|
||||
/**
|
||||
* 操作日志 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysOperLogMapper
|
||||
{
|
||||
/**
|
||||
* 新增操作日志
|
||||
*
|
||||
* @param operLog 操作日志对象
|
||||
*/
|
||||
public void insertOperlog(SysOperLog operLog);
|
||||
|
||||
/**
|
||||
* 查询系统操作日志集合
|
||||
*
|
||||
* @param operLog 操作日志对象
|
||||
* @return 操作日志集合
|
||||
*/
|
||||
public List<SysOperLog> selectOperLogList(SysOperLog operLog);
|
||||
|
||||
/**
|
||||
* 批量删除系统操作日志
|
||||
*
|
||||
* @param operIds 需要删除的操作日志ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteOperLogByIds(Long[] operIds);
|
||||
|
||||
/**
|
||||
* 查询操作日志详细
|
||||
*
|
||||
* @param operId 操作ID
|
||||
* @return 操作日志对象
|
||||
*/
|
||||
public SysOperLog selectOperLogById(Long operId);
|
||||
|
||||
/**
|
||||
* 清空操作日志
|
||||
*/
|
||||
public void cleanOperLog();
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.lingniu.idp.model.entity.SysPost;
|
||||
|
||||
/**
|
||||
* 岗位信息 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysPostMapper
|
||||
{
|
||||
/**
|
||||
* 查询岗位数据集合
|
||||
*
|
||||
* @param post 岗位信息
|
||||
* @return 岗位数据集合
|
||||
*/
|
||||
public List<SysPost> selectPostList(SysPost post);
|
||||
|
||||
/**
|
||||
* 查询所有岗位
|
||||
*
|
||||
* @return 岗位列表
|
||||
*/
|
||||
public List<SysPost> selectPostAll();
|
||||
|
||||
/**
|
||||
* 通过岗位ID查询岗位信息
|
||||
*
|
||||
* @param postId 岗位ID
|
||||
* @return 角色对象信息
|
||||
*/
|
||||
public SysPost selectPostById(Long postId);
|
||||
|
||||
/**
|
||||
* 根据用户ID获取岗位选择框列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 选中岗位ID列表
|
||||
*/
|
||||
public List<Long> selectPostListByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 查询用户所属岗位组
|
||||
*
|
||||
* @param userName 用户名
|
||||
* @return 结果
|
||||
*/
|
||||
public List<SysPost> selectPostsByUserName(String userName);
|
||||
|
||||
/**
|
||||
* 删除岗位信息
|
||||
*
|
||||
* @param postId 岗位ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deletePostById(Long postId);
|
||||
|
||||
/**
|
||||
* 批量删除岗位信息
|
||||
*
|
||||
* @param postIds 需要删除的岗位ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deletePostByIds(Long[] postIds);
|
||||
|
||||
/**
|
||||
* 修改岗位信息
|
||||
*
|
||||
* @param post 岗位信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updatePost(SysPost post);
|
||||
|
||||
/**
|
||||
* 新增岗位信息
|
||||
*
|
||||
* @param post 岗位信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertPost(SysPost post);
|
||||
|
||||
/**
|
||||
* 校验岗位名称
|
||||
*
|
||||
* @param postName 岗位名称
|
||||
* @return 结果
|
||||
*/
|
||||
public SysPost checkPostNameUnique(String postName);
|
||||
|
||||
/**
|
||||
* 校验岗位编码
|
||||
*
|
||||
* @param postCode 岗位编码
|
||||
* @return 结果
|
||||
*/
|
||||
public SysPost checkPostCodeUnique(String postCode);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.lingniu.idp.model.entity.SysRoleDept;
|
||||
|
||||
/**
|
||||
* 角色与部门关联表 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysRoleDeptMapper
|
||||
{
|
||||
/**
|
||||
* 通过角色ID删除角色和部门关联
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRoleDeptByRoleId(Long roleId);
|
||||
|
||||
/**
|
||||
* 批量删除角色部门关联信息
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRoleDept(Long[] ids);
|
||||
|
||||
/**
|
||||
* 查询部门使用数量
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int selectCountRoleDeptByDeptId(Long deptId);
|
||||
|
||||
/**
|
||||
* 批量新增角色部门信息
|
||||
*
|
||||
* @param roleDeptList 角色部门列表
|
||||
* @return 结果
|
||||
*/
|
||||
public int batchRoleDept(List<SysRoleDept> roleDeptList);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.lingniu.idp.model.entity.SysRole;
|
||||
|
||||
/**
|
||||
* 角色表 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysRoleMapper
|
||||
{
|
||||
/**
|
||||
* 根据条件分页查询角色数据
|
||||
*
|
||||
* @param role 角色信息
|
||||
* @return 角色数据集合信息
|
||||
*/
|
||||
public List<SysRole> selectRoleList(SysRole role);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询角色
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 角色列表
|
||||
*/
|
||||
public List<SysRole> selectRolePermissionByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 查询所有角色
|
||||
*
|
||||
* @return 角色列表
|
||||
*/
|
||||
public List<SysRole> selectRoleAll();
|
||||
|
||||
/**
|
||||
* 根据用户ID获取角色选择框列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 选中角色ID列表
|
||||
*/
|
||||
public List<Long> selectRoleListByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 通过角色ID查询角色
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @return 角色对象信息
|
||||
*/
|
||||
public SysRole selectRoleById(Long roleId);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询角色
|
||||
*
|
||||
* @param userName 用户名
|
||||
* @return 角色列表
|
||||
*/
|
||||
public List<SysRole> selectRolesByUserName(String userName);
|
||||
|
||||
/**
|
||||
* 校验角色名称是否唯一
|
||||
*
|
||||
* @param roleName 角色名称
|
||||
* @return 角色信息
|
||||
*/
|
||||
public SysRole checkRoleNameUnique(String roleName);
|
||||
|
||||
/**
|
||||
* 校验角色权限是否唯一
|
||||
*
|
||||
* @param roleKey 角色权限
|
||||
* @return 角色信息
|
||||
*/
|
||||
public SysRole checkRoleKeyUnique(String roleKey);
|
||||
|
||||
/**
|
||||
* 修改角色信息
|
||||
*
|
||||
* @param role 角色信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateRole(SysRole role);
|
||||
|
||||
/**
|
||||
* 新增角色信息
|
||||
*
|
||||
* @param role 角色信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertRole(SysRole role);
|
||||
|
||||
/**
|
||||
* 通过角色ID删除角色
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRoleById(Long roleId);
|
||||
|
||||
/**
|
||||
* 批量删除角色信息
|
||||
*
|
||||
* @param roleIds 需要删除的角色ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRoleByIds(Long[] roleIds);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.lingniu.idp.model.entity.SysRoleMenu;
|
||||
|
||||
/**
|
||||
* 角色与菜单关联表 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysRoleMenuMapper
|
||||
{
|
||||
/**
|
||||
* 查询菜单使用数量
|
||||
*
|
||||
* @param menuId 菜单ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int checkMenuExistRole(Long menuId);
|
||||
|
||||
/**
|
||||
* 通过角色ID删除角色和菜单关联
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRoleMenuByRoleId(Long roleId);
|
||||
|
||||
/**
|
||||
* 批量删除角色菜单关联信息
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRoleMenu(Long[] ids);
|
||||
|
||||
/**
|
||||
* 批量新增角色菜单信息
|
||||
*
|
||||
* @param roleMenuList 角色菜单列表
|
||||
* @return 结果
|
||||
*/
|
||||
public int batchRoleMenu(List<SysRoleMenu> roleMenuList);
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.lingniu.idp.model.entity.SysUser;
|
||||
|
||||
/**
|
||||
* 用户表 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysUserMapper
|
||||
{
|
||||
/**
|
||||
* 根据条件分页查询用户列表
|
||||
*
|
||||
* @param sysUser 用户信息
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
public List<SysUser> selectUserList(SysUser sysUser);
|
||||
|
||||
/**
|
||||
* 根据条件分页查询已配用户角色列表
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
public List<SysUser> selectAllocatedList(SysUser user);
|
||||
|
||||
/**
|
||||
* 根据条件分页查询未分配用户角色列表
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 用户信息集合信息
|
||||
*/
|
||||
public List<SysUser> selectUnallocatedList(SysUser user);
|
||||
|
||||
/**
|
||||
* 通过用户名查询用户
|
||||
*
|
||||
* @param userName 用户名
|
||||
* @return 用户对象信息
|
||||
*/
|
||||
public SysUser selectUserByUserName(String userName);
|
||||
|
||||
/**
|
||||
* 通过用户ID查询用户
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 用户对象信息
|
||||
*/
|
||||
public SysUser selectUserById(Long userId);
|
||||
|
||||
/**
|
||||
* 新增用户信息
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertUser(SysUser user);
|
||||
|
||||
/**
|
||||
* 修改用户信息
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateUser(SysUser user);
|
||||
|
||||
/**
|
||||
* 修改用户头像
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param avatar 头像地址
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateUserAvatar(@Param("userId") Long userId, @Param("avatar") String avatar);
|
||||
|
||||
/**
|
||||
* 修改用户状态
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param status 状态
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateUserStatus(@Param("userId") Long userId, @Param("status") String status);
|
||||
|
||||
/**
|
||||
* 更新用户登录信息(IP和登录时间)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param loginIp 登录IP地址
|
||||
* @param loginDate 登录时间
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateLoginInfo(@Param("userId") Long userId, @Param("loginIp") String loginIp, @Param("loginDate") Date loginDate);
|
||||
|
||||
/**
|
||||
* 重置用户密码
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param password 密码
|
||||
* @return 结果
|
||||
*/
|
||||
public int resetUserPwd(@Param("userId") Long userId, @Param("password") String password);
|
||||
|
||||
/**
|
||||
* 通过用户ID删除用户
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteUserById(Long userId);
|
||||
|
||||
/**
|
||||
* 批量删除用户信息
|
||||
*
|
||||
* @param userIds 需要删除的用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteUserByIds(Long[] userIds);
|
||||
|
||||
/**
|
||||
* 校验用户名称是否唯一
|
||||
*
|
||||
* @param userName 用户名称
|
||||
* @return 结果
|
||||
*/
|
||||
public SysUser checkUserNameUnique(String userName);
|
||||
|
||||
/**
|
||||
* 校验手机号码是否唯一
|
||||
*
|
||||
* @param phonenumber 手机号码
|
||||
* @return 结果
|
||||
*/
|
||||
public SysUser checkPhoneUnique(String phonenumber);
|
||||
|
||||
/**
|
||||
* 校验email是否唯一
|
||||
*
|
||||
* @param email 用户邮箱
|
||||
* @return 结果
|
||||
*/
|
||||
public SysUser checkEmailUnique(String email);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.lingniu.idp.model.entity.SysUserPost;
|
||||
|
||||
/**
|
||||
* 用户与岗位关联表 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysUserPostMapper
|
||||
{
|
||||
/**
|
||||
* 通过用户ID删除用户和岗位关联
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteUserPostByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 通过岗位ID查询岗位使用数量
|
||||
*
|
||||
* @param postId 岗位ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int countUserPostById(Long postId);
|
||||
|
||||
/**
|
||||
* 批量删除用户和岗位关联
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteUserPost(Long[] ids);
|
||||
|
||||
/**
|
||||
* 批量新增用户岗位信息
|
||||
*
|
||||
* @param userPostList 用户岗位列表
|
||||
* @return 结果
|
||||
*/
|
||||
public int batchUserPost(List<SysUserPost> userPostList);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.lingniu.idp.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.lingniu.idp.model.entity.SysUserRole;
|
||||
|
||||
/**
|
||||
* 用户与角色关联表 数据层
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysUserRoleMapper
|
||||
{
|
||||
/**
|
||||
* 通过用户ID删除用户和角色关联
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteUserRoleByUserId(Long userId);
|
||||
|
||||
/**
|
||||
* 批量删除用户和角色关联
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteUserRole(Long[] ids);
|
||||
|
||||
/**
|
||||
* 通过角色ID查询角色使用数量
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int countUserRoleByRoleId(Long roleId);
|
||||
|
||||
/**
|
||||
* 批量新增用户角色信息
|
||||
*
|
||||
* @param userRoleList 用户角色列表
|
||||
* @return 结果
|
||||
*/
|
||||
public int batchUserRole(List<SysUserRole> userRoleList);
|
||||
|
||||
/**
|
||||
* 删除用户和角色关联信息
|
||||
*
|
||||
* @param userRole 用户和角色关联信息
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteUserRoleInfo(SysUserRole userRole);
|
||||
|
||||
/**
|
||||
* 批量取消授权用户角色
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param userIds 需要删除的用户数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds);
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package org.lingniu.idp.model.base;
|
||||
|
||||
import org.lingniu.idp.utils.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 操作消息提醒
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class AjaxResult extends HashMap<String, Object>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 状态码 */
|
||||
public static final String CODE_TAG = "code";
|
||||
|
||||
/** 返回内容 */
|
||||
public static final String MSG_TAG = "msg";
|
||||
|
||||
/** 数据对象 */
|
||||
public static final String DATA_TAG = "data";
|
||||
|
||||
/**
|
||||
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
|
||||
*/
|
||||
public AjaxResult()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化一个新创建的 AjaxResult 对象
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 返回内容
|
||||
*/
|
||||
public AjaxResult(int code, String msg)
|
||||
{
|
||||
super.put(CODE_TAG, code);
|
||||
super.put(MSG_TAG, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化一个新创建的 AjaxResult 对象
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
*/
|
||||
public AjaxResult(int code, String msg, Object data)
|
||||
{
|
||||
super.put(CODE_TAG, code);
|
||||
super.put(MSG_TAG, msg);
|
||||
if (StringUtils.isNotNull(data))
|
||||
{
|
||||
super.put(DATA_TAG, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success()
|
||||
{
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功数据
|
||||
*
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success(Object data)
|
||||
{
|
||||
return AjaxResult.success("操作成功", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success(String msg)
|
||||
{
|
||||
return AjaxResult.success(msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success(String msg, Object data)
|
||||
{
|
||||
return new AjaxResult(HttpStatus.OK.value(), msg, data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static AjaxResult error()
|
||||
{
|
||||
return AjaxResult.error("操作失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static AjaxResult error(String msg)
|
||||
{
|
||||
return AjaxResult.error(msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static AjaxResult error(String msg, Object data)
|
||||
{
|
||||
return new AjaxResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), msg, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 返回内容
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static AjaxResult error(int code, String msg)
|
||||
{
|
||||
return new AjaxResult(code, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为成功消息
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isSuccess()
|
||||
{
|
||||
return Objects.equals(HttpStatus.OK.value(), this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否为错误消息
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isError()
|
||||
{
|
||||
return Objects.equals(HttpStatus.INTERNAL_SERVER_ERROR.value(), this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
* 方便链式调用
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @return 数据对象
|
||||
*/
|
||||
@Override
|
||||
public AjaxResult put(String key, Object value)
|
||||
{
|
||||
super.put(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package org.lingniu.idp.model.base;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Entity基类
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class BaseEntity implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 搜索值 */
|
||||
@JsonIgnore
|
||||
private String searchValue;
|
||||
|
||||
/** 创建者 */
|
||||
private String createBy;
|
||||
|
||||
/** 创建时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
private String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
/** 请求参数 */
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
private Map<String, Object> params;
|
||||
|
||||
public String getSearchValue()
|
||||
{
|
||||
return searchValue;
|
||||
}
|
||||
|
||||
public void setSearchValue(String searchValue)
|
||||
{
|
||||
this.searchValue = searchValue;
|
||||
}
|
||||
|
||||
public String getCreateBy()
|
||||
{
|
||||
return createBy;
|
||||
}
|
||||
|
||||
public void setCreateBy(String createBy)
|
||||
{
|
||||
this.createBy = createBy;
|
||||
}
|
||||
|
||||
public Date getCreateTime()
|
||||
{
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime)
|
||||
{
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getUpdateBy()
|
||||
{
|
||||
return updateBy;
|
||||
}
|
||||
|
||||
public void setUpdateBy(String updateBy)
|
||||
{
|
||||
this.updateBy = updateBy;
|
||||
}
|
||||
|
||||
public Date getUpdateTime()
|
||||
{
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime)
|
||||
{
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public String getRemark()
|
||||
{
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark)
|
||||
{
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public Map<String, Object> getParams()
|
||||
{
|
||||
if (params == null)
|
||||
{
|
||||
params = new HashMap<>();
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(Map<String, Object> params)
|
||||
{
|
||||
this.params = params;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.lingniu.idp.model.base;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 通用返回
|
||||
*
|
||||
* @param <T> 数据泛型
|
||||
*/
|
||||
@Data
|
||||
public class CommonResult<T> implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 错误码
|
||||
*
|
||||
*/
|
||||
private Integer code;
|
||||
/**
|
||||
* 错误提示,用户可阅读
|
||||
*
|
||||
*/
|
||||
private String msg;
|
||||
/**
|
||||
* 返回数据
|
||||
*/
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* 将传入的 result 对象,转换成另外一个泛型结果的对象
|
||||
*
|
||||
* 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。
|
||||
*
|
||||
* @param result 传入的 result 对象
|
||||
* @param <T> 返回的泛型
|
||||
* @return 新的 CommonResult 对象
|
||||
*/
|
||||
public static <T> CommonResult<T> error(CommonResult<?> result) {
|
||||
return error(result.getCode(), result.getMsg());
|
||||
}
|
||||
|
||||
public static <T> CommonResult<T> error(Integer code, String message) {
|
||||
Assert.notEquals(HttpStatus.OK.value(), code, "code 必须是错误的!");
|
||||
CommonResult<T> result = new CommonResult<>();
|
||||
result.code = code;
|
||||
result.msg = message;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static <T> CommonResult<T> success(T data) {
|
||||
CommonResult<T> result = new CommonResult<>();
|
||||
result.code = HttpStatus.OK.value();
|
||||
result.data = data;
|
||||
result.msg = "";
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isSuccess(Integer code) {
|
||||
return Objects.equals(code, HttpStatus.OK.value());
|
||||
}
|
||||
|
||||
@JsonIgnore // 避免 jackson 序列化
|
||||
public boolean isSuccess() {
|
||||
return isSuccess(code);
|
||||
}
|
||||
|
||||
@JsonIgnore // 避免 jackson 序列化
|
||||
public boolean isError() {
|
||||
return !isSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package org.lingniu.idp.model.base;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import org.lingniu.idp.constant.UserConstants;
|
||||
import org.lingniu.idp.model.entity.SysDept;
|
||||
import org.lingniu.idp.model.entity.SysMenu;
|
||||
import org.lingniu.idp.utils.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Treeselect树结构实体类
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class TreeSelect implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 节点ID */
|
||||
private Long id;
|
||||
|
||||
/** 节点名称 */
|
||||
private String label;
|
||||
|
||||
/** 节点禁用 */
|
||||
private boolean disabled = false;
|
||||
|
||||
/** 子节点 */
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
private List<TreeSelect> children;
|
||||
|
||||
public TreeSelect()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TreeSelect(SysDept dept)
|
||||
{
|
||||
this.id = dept.getDeptId();
|
||||
this.label = dept.getDeptName();
|
||||
this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
|
||||
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public TreeSelect(SysMenu menu)
|
||||
{
|
||||
this.id = menu.getMenuId();
|
||||
this.label = menu.getMenuName();
|
||||
this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label)
|
||||
{
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public boolean isDisabled()
|
||||
{
|
||||
return disabled;
|
||||
}
|
||||
|
||||
public void setDisabled(boolean disabled)
|
||||
{
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
public List<TreeSelect> getChildren()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<TreeSelect> children)
|
||||
{
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.lingniu.idp.model.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 用户登录对象
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class AccountLoginDto
|
||||
{
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 用户密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 唯一标识
|
||||
*/
|
||||
private String uuid;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package org.lingniu.idp.model.dto;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.lingniu.idp.model.entity.SysUser;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 登录用户身份权限
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class LoginUser implements UserDetails
|
||||
{
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 用户唯一标识
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 登录时间
|
||||
*/
|
||||
private Long loginTime;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Long expireTime;
|
||||
|
||||
/**
|
||||
* 登录IP地址
|
||||
*/
|
||||
private String ipaddr;
|
||||
|
||||
/**
|
||||
* 登录地点
|
||||
*/
|
||||
private String loginLocation;
|
||||
|
||||
/**
|
||||
* 浏览器类型
|
||||
*/
|
||||
private String browser;
|
||||
|
||||
/**
|
||||
* 操作系统
|
||||
*/
|
||||
private String os;
|
||||
|
||||
/**
|
||||
* 权限列表
|
||||
*/
|
||||
private Set<String> permissions;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
private SysUser user;
|
||||
|
||||
public LoginUser()
|
||||
{
|
||||
}
|
||||
|
||||
public LoginUser(SysUser user, Set<String> permissions)
|
||||
{
|
||||
this.user = user;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
|
||||
{
|
||||
this.userId = userId;
|
||||
this.deptId = deptId;
|
||||
this.user = user;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public String getPassword()
|
||||
{
|
||||
return user.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername()
|
||||
{
|
||||
return user.getUserName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 账户是否未过期,过期无法验证
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isAccountNonExpired()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定用户是否解锁,锁定的用户无法进行身份验证
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isAccountNonLocked()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可用 ,禁用的用户不能身份验证
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.lingniu.idp.model.dto;
|
||||
|
||||
/**
|
||||
* 用户注册对象
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class RegisterAccountDto extends AccountLoginDto
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import org.lingniu.idp.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 缓存信息
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SysCache
|
||||
{
|
||||
/** 缓存名称 */
|
||||
private String cacheName = "";
|
||||
|
||||
/** 缓存键名 */
|
||||
private String cacheKey = "";
|
||||
|
||||
/** 缓存内容 */
|
||||
private String cacheValue = "";
|
||||
|
||||
/** 备注 */
|
||||
private String remark = "";
|
||||
|
||||
public SysCache()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public SysCache(String cacheName, String remark)
|
||||
{
|
||||
this.cacheName = cacheName;
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public SysCache(String cacheName, String cacheKey, String cacheValue)
|
||||
{
|
||||
this.cacheName = StringUtils.replace(cacheName, ":", "");
|
||||
this.cacheKey = StringUtils.replace(cacheKey, cacheName, "");
|
||||
this.cacheValue = cacheValue;
|
||||
}
|
||||
|
||||
public String getCacheName()
|
||||
{
|
||||
return cacheName;
|
||||
}
|
||||
|
||||
public void setCacheName(String cacheName)
|
||||
{
|
||||
this.cacheName = cacheName;
|
||||
}
|
||||
|
||||
public String getCacheKey()
|
||||
{
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
public void setCacheKey(String cacheKey)
|
||||
{
|
||||
this.cacheKey = cacheKey;
|
||||
}
|
||||
|
||||
public String getCacheValue()
|
||||
{
|
||||
return cacheValue;
|
||||
}
|
||||
|
||||
public void setCacheValue(String cacheValue)
|
||||
{
|
||||
this.cacheValue = cacheValue;
|
||||
}
|
||||
|
||||
public String getRemark()
|
||||
{
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark)
|
||||
{
|
||||
this.remark = remark;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.lingniu.idp.model.base.BaseEntity;
|
||||
|
||||
/**
|
||||
* 参数配置表 sys_config
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SysConfig extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 参数主键 */
|
||||
private Long configId;
|
||||
|
||||
/** 参数名称 */
|
||||
private String configName;
|
||||
|
||||
/** 参数键名 */
|
||||
private String configKey;
|
||||
|
||||
/** 参数键值 */
|
||||
private String configValue;
|
||||
|
||||
/** 系统内置(Y是 N否) */
|
||||
private String configType;
|
||||
|
||||
public Long getConfigId()
|
||||
{
|
||||
return configId;
|
||||
}
|
||||
|
||||
public void setConfigId(Long configId)
|
||||
{
|
||||
this.configId = configId;
|
||||
}
|
||||
|
||||
@NotBlank(message = "参数名称不能为空")
|
||||
@Size(min = 0, max = 100, message = "参数名称不能超过100个字符")
|
||||
public String getConfigName()
|
||||
{
|
||||
return configName;
|
||||
}
|
||||
|
||||
public void setConfigName(String configName)
|
||||
{
|
||||
this.configName = configName;
|
||||
}
|
||||
|
||||
@NotBlank(message = "参数键名长度不能为空")
|
||||
@Size(min = 0, max = 100, message = "参数键名长度不能超过100个字符")
|
||||
public String getConfigKey()
|
||||
{
|
||||
return configKey;
|
||||
}
|
||||
|
||||
public void setConfigKey(String configKey)
|
||||
{
|
||||
this.configKey = configKey;
|
||||
}
|
||||
|
||||
@NotBlank(message = "参数键值不能为空")
|
||||
@Size(min = 0, max = 500, message = "参数键值长度不能超过500个字符")
|
||||
public String getConfigValue()
|
||||
{
|
||||
return configValue;
|
||||
}
|
||||
|
||||
public void setConfigValue(String configValue)
|
||||
{
|
||||
this.configValue = configValue;
|
||||
}
|
||||
|
||||
public String getConfigType()
|
||||
{
|
||||
return configType;
|
||||
}
|
||||
|
||||
public void setConfigType(String configType)
|
||||
{
|
||||
this.configType = configType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("configId", getConfigId())
|
||||
.append("configName", getConfigName())
|
||||
.append("configKey", getConfigKey())
|
||||
.append("configValue", getConfigValue())
|
||||
.append("configType", getConfigType())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("remark", getRemark())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.lingniu.idp.model.base.BaseEntity;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部门表 sys_dept
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class SysDept extends BaseEntity
|
||||
{
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 部门ID */
|
||||
private Long deptId;
|
||||
|
||||
/** 父部门ID */
|
||||
private Long parentId;
|
||||
|
||||
/** 祖级列表 */
|
||||
private String ancestors;
|
||||
|
||||
/** 部门名称 */
|
||||
@NotBlank(message = "部门名称不能为空")
|
||||
@Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
|
||||
private String deptName;
|
||||
|
||||
/** 显示顺序 */
|
||||
@NotNull(message = "显示顺序不能为空")
|
||||
private Integer orderNum;
|
||||
|
||||
/** 负责人 */
|
||||
private String leader;
|
||||
|
||||
/** 联系电话 */
|
||||
@Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
|
||||
private String phone;
|
||||
|
||||
/** 邮箱 */
|
||||
@Email(message = "邮箱格式不正确")
|
||||
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
|
||||
private String email;
|
||||
|
||||
/** 部门状态:0正常,1停用 */
|
||||
private String status;
|
||||
|
||||
/** 删除标志(0代表存在 2代表删除) */
|
||||
private String delFlag;
|
||||
|
||||
/** 父部门名称 */
|
||||
private String parentName;
|
||||
/**运维区域*/
|
||||
private Long areaId;
|
||||
|
||||
/** 子部门 */
|
||||
private List<SysDept> children = new ArrayList<SysDept>();
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("deptId", getDeptId())
|
||||
.append("parentId", getParentId())
|
||||
.append("ancestors", getAncestors())
|
||||
.append("deptName", getDeptName())
|
||||
.append("orderNum", getOrderNum())
|
||||
.append("leader", getLeader())
|
||||
.append("phone", getPhone())
|
||||
.append("email", getEmail())
|
||||
.append("status", getStatus())
|
||||
.append("delFlag", getDelFlag())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.lingniu.idp.model.base.BaseEntity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 系统访问记录表 sys_logininfor
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SysLogininfor extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** ID */
|
||||
private Long infoId;
|
||||
|
||||
/** 用户账号 */
|
||||
private String userName;
|
||||
|
||||
/** 登录状态 0成功 1失败 */
|
||||
private String status;
|
||||
|
||||
/** 登录IP地址 */
|
||||
private String ipaddr;
|
||||
|
||||
/** 登录地点 */
|
||||
private String loginLocation;
|
||||
|
||||
/** 浏览器类型 */
|
||||
private String browser;
|
||||
|
||||
/** 操作系统 */
|
||||
private String os;
|
||||
|
||||
/** 提示消息 */
|
||||
private String msg;
|
||||
|
||||
/** 访问时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date loginTime;
|
||||
|
||||
public Long getInfoId()
|
||||
{
|
||||
return infoId;
|
||||
}
|
||||
|
||||
public void setInfoId(Long infoId)
|
||||
{
|
||||
this.infoId = infoId;
|
||||
}
|
||||
|
||||
public String getUserName()
|
||||
{
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName)
|
||||
{
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getIpaddr()
|
||||
{
|
||||
return ipaddr;
|
||||
}
|
||||
|
||||
public void setIpaddr(String ipaddr)
|
||||
{
|
||||
this.ipaddr = ipaddr;
|
||||
}
|
||||
|
||||
public String getLoginLocation()
|
||||
{
|
||||
return loginLocation;
|
||||
}
|
||||
|
||||
public void setLoginLocation(String loginLocation)
|
||||
{
|
||||
this.loginLocation = loginLocation;
|
||||
}
|
||||
|
||||
public String getBrowser()
|
||||
{
|
||||
return browser;
|
||||
}
|
||||
|
||||
public void setBrowser(String browser)
|
||||
{
|
||||
this.browser = browser;
|
||||
}
|
||||
|
||||
public String getOs()
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
public void setOs(String os)
|
||||
{
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
public String getMsg()
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg)
|
||||
{
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public Date getLoginTime()
|
||||
{
|
||||
return loginTime;
|
||||
}
|
||||
|
||||
public void setLoginTime(Date loginTime)
|
||||
{
|
||||
this.loginTime = loginTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.lingniu.idp.model.base.BaseEntity;
|
||||
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 菜单权限表 sys_menu
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class SysMenu extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 菜单ID */
|
||||
private Long menuId;
|
||||
|
||||
/** 菜单名称 */
|
||||
private String menuName;
|
||||
|
||||
/** 父菜单名称 */
|
||||
private String parentName;
|
||||
|
||||
/** 父菜单ID */
|
||||
private Long parentId;
|
||||
|
||||
/** 显示顺序 */
|
||||
private Integer orderNum;
|
||||
|
||||
/** 路由地址 */
|
||||
private String path;
|
||||
|
||||
/** 组件路径 */
|
||||
private String component;
|
||||
|
||||
/** 路由参数 */
|
||||
private String query;
|
||||
|
||||
/** 路由名称,默认和路由地址相同的驼峰格式(注意:因为vue3版本的router会删除名称相同路由,为避免名字的冲突,特殊情况可以自定义) */
|
||||
private String routeName;
|
||||
|
||||
/** 是否为外链(0是 1否) */
|
||||
private String isFrame;
|
||||
|
||||
/** 是否缓存(0缓存 1不缓存) */
|
||||
private String isCache;
|
||||
|
||||
/** 类型(M目录 C菜单 F按钮) */
|
||||
private String menuType;
|
||||
|
||||
/** 显示状态(0显示 1隐藏) */
|
||||
private String visible;
|
||||
|
||||
/** 菜单状态(0正常 1停用) */
|
||||
private String status;
|
||||
|
||||
/** 权限字符串 */
|
||||
private String perms;
|
||||
|
||||
/** 菜单图标 */
|
||||
private String icon;
|
||||
|
||||
/** 子菜单 */
|
||||
private List<SysMenu> children = new ArrayList<SysMenu>();
|
||||
|
||||
public Long getMenuId()
|
||||
{
|
||||
return menuId;
|
||||
}
|
||||
|
||||
public void setMenuId(Long menuId)
|
||||
{
|
||||
this.menuId = menuId;
|
||||
}
|
||||
|
||||
@NotBlank(message = "菜单名称不能为空")
|
||||
@Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
|
||||
public String getMenuName()
|
||||
{
|
||||
return menuName;
|
||||
}
|
||||
|
||||
public void setMenuName(String menuName)
|
||||
{
|
||||
this.menuName = menuName;
|
||||
}
|
||||
|
||||
public String getParentName()
|
||||
{
|
||||
return parentName;
|
||||
}
|
||||
|
||||
public void setParentName(String parentName)
|
||||
{
|
||||
this.parentName = parentName;
|
||||
}
|
||||
|
||||
public Long getParentId()
|
||||
{
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(Long parentId)
|
||||
{
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
@NotNull(message = "显示顺序不能为空")
|
||||
public Integer getOrderNum()
|
||||
{
|
||||
return orderNum;
|
||||
}
|
||||
|
||||
public void setOrderNum(Integer orderNum)
|
||||
{
|
||||
this.orderNum = orderNum;
|
||||
}
|
||||
|
||||
@Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path)
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
|
||||
public String getComponent()
|
||||
{
|
||||
return component;
|
||||
}
|
||||
|
||||
public void setComponent(String component)
|
||||
{
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
public String getQuery()
|
||||
{
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(String query)
|
||||
{
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public String getRouteName()
|
||||
{
|
||||
return routeName;
|
||||
}
|
||||
|
||||
public void setRouteName(String routeName)
|
||||
{
|
||||
this.routeName = routeName;
|
||||
}
|
||||
|
||||
public String getIsFrame()
|
||||
{
|
||||
return isFrame;
|
||||
}
|
||||
|
||||
public void setIsFrame(String isFrame)
|
||||
{
|
||||
this.isFrame = isFrame;
|
||||
}
|
||||
|
||||
public String getIsCache()
|
||||
{
|
||||
return isCache;
|
||||
}
|
||||
|
||||
public void setIsCache(String isCache)
|
||||
{
|
||||
this.isCache = isCache;
|
||||
}
|
||||
|
||||
@NotBlank(message = "菜单类型不能为空")
|
||||
public String getMenuType()
|
||||
{
|
||||
return menuType;
|
||||
}
|
||||
|
||||
public void setMenuType(String menuType)
|
||||
{
|
||||
this.menuType = menuType;
|
||||
}
|
||||
|
||||
public String getVisible()
|
||||
{
|
||||
return visible;
|
||||
}
|
||||
|
||||
public void setVisible(String visible)
|
||||
{
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
|
||||
public String getPerms()
|
||||
{
|
||||
return perms;
|
||||
}
|
||||
|
||||
public void setPerms(String perms)
|
||||
{
|
||||
this.perms = perms;
|
||||
}
|
||||
|
||||
public String getIcon()
|
||||
{
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void setIcon(String icon)
|
||||
{
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public List<SysMenu> getChildren()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<SysMenu> children)
|
||||
{
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("menuId", getMenuId())
|
||||
.append("menuName", getMenuName())
|
||||
.append("parentId", getParentId())
|
||||
.append("orderNum", getOrderNum())
|
||||
.append("path", getPath())
|
||||
.append("component", getComponent())
|
||||
.append("query", getQuery())
|
||||
.append("routeName", getRouteName())
|
||||
.append("isFrame", getIsFrame())
|
||||
.append("IsCache", getIsCache())
|
||||
.append("menuType", getMenuType())
|
||||
.append("visible", getVisible())
|
||||
.append("status ", getStatus())
|
||||
.append("perms", getPerms())
|
||||
.append("icon", getIcon())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("remark", getRemark())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.lingniu.idp.model.base.BaseEntity;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 操作日志记录表 oper_log
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SysOperLog extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 日志主键 */
|
||||
private Long operId;
|
||||
|
||||
/** 操作模块 */
|
||||
private String title;
|
||||
|
||||
/** 业务类型(0其它 1新增 2修改 3删除) */
|
||||
private Integer businessType;
|
||||
|
||||
/** 业务类型数组 */
|
||||
private Integer[] businessTypes;
|
||||
|
||||
/** 请求方法 */
|
||||
private String method;
|
||||
|
||||
/** 请求方式 */
|
||||
private String requestMethod;
|
||||
|
||||
/** 操作类别(0其它 1后台用户 2手机端用户) */
|
||||
private Integer operatorType;
|
||||
|
||||
/** 操作人员 */
|
||||
private String operName;
|
||||
|
||||
/** 部门名称 */
|
||||
private String deptName;
|
||||
|
||||
/** 请求url */
|
||||
private String operUrl;
|
||||
|
||||
/** 操作地址 */
|
||||
private String operIp;
|
||||
|
||||
/** 操作地点 */
|
||||
private String operLocation;
|
||||
|
||||
/** 请求参数 */
|
||||
private String operParam;
|
||||
|
||||
/** 返回参数 */
|
||||
private String jsonResult;
|
||||
|
||||
/** 操作状态(0正常 1异常) */
|
||||
private Integer status;
|
||||
|
||||
/** 错误消息 */
|
||||
private String errorMsg;
|
||||
|
||||
/** 操作时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date operTime;
|
||||
|
||||
/** 消耗时间 */
|
||||
private Long costTime;
|
||||
|
||||
public Long getOperId()
|
||||
{
|
||||
return operId;
|
||||
}
|
||||
|
||||
public void setOperId(Long operId)
|
||||
{
|
||||
this.operId = operId;
|
||||
}
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Integer getBusinessType()
|
||||
{
|
||||
return businessType;
|
||||
}
|
||||
|
||||
public void setBusinessType(Integer businessType)
|
||||
{
|
||||
this.businessType = businessType;
|
||||
}
|
||||
|
||||
public Integer[] getBusinessTypes()
|
||||
{
|
||||
return businessTypes;
|
||||
}
|
||||
|
||||
public void setBusinessTypes(Integer[] businessTypes)
|
||||
{
|
||||
this.businessTypes = businessTypes;
|
||||
}
|
||||
|
||||
public String getMethod()
|
||||
{
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method)
|
||||
{
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public String getRequestMethod()
|
||||
{
|
||||
return requestMethod;
|
||||
}
|
||||
|
||||
public void setRequestMethod(String requestMethod)
|
||||
{
|
||||
this.requestMethod = requestMethod;
|
||||
}
|
||||
|
||||
public Integer getOperatorType()
|
||||
{
|
||||
return operatorType;
|
||||
}
|
||||
|
||||
public void setOperatorType(Integer operatorType)
|
||||
{
|
||||
this.operatorType = operatorType;
|
||||
}
|
||||
|
||||
public String getOperName()
|
||||
{
|
||||
return operName;
|
||||
}
|
||||
|
||||
public void setOperName(String operName)
|
||||
{
|
||||
this.operName = operName;
|
||||
}
|
||||
|
||||
public String getDeptName()
|
||||
{
|
||||
return deptName;
|
||||
}
|
||||
|
||||
public void setDeptName(String deptName)
|
||||
{
|
||||
this.deptName = deptName;
|
||||
}
|
||||
|
||||
public String getOperUrl()
|
||||
{
|
||||
return operUrl;
|
||||
}
|
||||
|
||||
public void setOperUrl(String operUrl)
|
||||
{
|
||||
this.operUrl = operUrl;
|
||||
}
|
||||
|
||||
public String getOperIp()
|
||||
{
|
||||
return operIp;
|
||||
}
|
||||
|
||||
public void setOperIp(String operIp)
|
||||
{
|
||||
this.operIp = operIp;
|
||||
}
|
||||
|
||||
public String getOperLocation()
|
||||
{
|
||||
return operLocation;
|
||||
}
|
||||
|
||||
public void setOperLocation(String operLocation)
|
||||
{
|
||||
this.operLocation = operLocation;
|
||||
}
|
||||
|
||||
public String getOperParam()
|
||||
{
|
||||
return operParam;
|
||||
}
|
||||
|
||||
public void setOperParam(String operParam)
|
||||
{
|
||||
this.operParam = operParam;
|
||||
}
|
||||
|
||||
public String getJsonResult()
|
||||
{
|
||||
return jsonResult;
|
||||
}
|
||||
|
||||
public void setJsonResult(String jsonResult)
|
||||
{
|
||||
this.jsonResult = jsonResult;
|
||||
}
|
||||
|
||||
public Integer getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getErrorMsg()
|
||||
{
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
public void setErrorMsg(String errorMsg)
|
||||
{
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public Date getOperTime()
|
||||
{
|
||||
return operTime;
|
||||
}
|
||||
|
||||
public void setOperTime(Date operTime)
|
||||
{
|
||||
this.operTime = operTime;
|
||||
}
|
||||
|
||||
public Long getCostTime()
|
||||
{
|
||||
return costTime;
|
||||
}
|
||||
|
||||
public void setCostTime(Long costTime)
|
||||
{
|
||||
this.costTime = costTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.lingniu.idp.model.base.BaseEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 岗位表 sys_post
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class SysPost extends BaseEntity
|
||||
{
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 岗位序号 */
|
||||
private Long postId;
|
||||
|
||||
/** 岗位编码 */
|
||||
@NotBlank(message = "岗位编码不能为空")
|
||||
@Size(min = 0, max = 64, message = "岗位编码长度不能超过64个字符")
|
||||
private String postCode;
|
||||
|
||||
/** 岗位名称 */
|
||||
@NotBlank(message = "岗位名称不能为空")
|
||||
@Size(min = 0, max = 50, message = "岗位名称长度不能超过50个字符")
|
||||
private String postName;
|
||||
|
||||
/** 岗位排序 */
|
||||
@NotNull(message = "显示顺序不能为空")
|
||||
private Integer postSort;
|
||||
|
||||
/** 状态(0正常 1停用) */
|
||||
private String status;
|
||||
|
||||
/** 用户是否存在此岗位标识 默认不存在 */
|
||||
private boolean flag = false;
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("postId", getPostId())
|
||||
.append("postCode", getPostCode())
|
||||
.append("postName", getPostName())
|
||||
.append("postSort", getPostSort())
|
||||
.append("status", getStatus())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("remark", getRemark())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.lingniu.idp.model.base.BaseEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 角色表 sys_role
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class SysRole extends BaseEntity
|
||||
{
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 角色ID */
|
||||
private Long roleId;
|
||||
|
||||
/** 角色名称 */
|
||||
@NotBlank(message = "角色名称不能为空")
|
||||
@Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
|
||||
private String roleName;
|
||||
|
||||
/** 角色权限 */
|
||||
@NotBlank(message = "权限字符不能为空")
|
||||
@Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
|
||||
private String roleKey;
|
||||
|
||||
/** 角色排序 */
|
||||
@NotNull(message = "显示顺序不能为空")
|
||||
private Integer roleSort;
|
||||
|
||||
/** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
|
||||
private String dataScope;
|
||||
|
||||
/** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
|
||||
private boolean menuCheckStrictly;
|
||||
|
||||
/** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */
|
||||
private boolean deptCheckStrictly;
|
||||
|
||||
/** 角色状态(0正常 1停用) */
|
||||
private String status;
|
||||
|
||||
/** 删除标志(0代表存在 2代表删除) */
|
||||
private String delFlag;
|
||||
|
||||
/** 用户是否存在此角色标识 默认不存在 */
|
||||
private boolean flag = false;
|
||||
|
||||
/** 菜单组 */
|
||||
private Long[] menuIds;
|
||||
|
||||
/** 部门组(数据权限) */
|
||||
private Long[] deptIds;
|
||||
|
||||
/** 角色菜单权限 */
|
||||
private Set<String> permissions;
|
||||
public SysRole(Long roleId){
|
||||
this.roleId = roleId;
|
||||
}
|
||||
public boolean isAdmin()
|
||||
{
|
||||
return isAdmin(this.roleId);
|
||||
}
|
||||
|
||||
public static boolean isAdmin(Long roleId)
|
||||
{
|
||||
return roleId != null && 1L == roleId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("roleId", getRoleId())
|
||||
.append("roleName", getRoleName())
|
||||
.append("roleKey", getRoleKey())
|
||||
.append("roleSort", getRoleSort())
|
||||
.append("dataScope", getDataScope())
|
||||
.append("menuCheckStrictly", isMenuCheckStrictly())
|
||||
.append("deptCheckStrictly", isDeptCheckStrictly())
|
||||
.append("status", getStatus())
|
||||
.append("delFlag", getDelFlag())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("remark", getRemark())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
/**
|
||||
* 角色和部门关联 sys_role_dept
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SysRoleDept
|
||||
{
|
||||
/** 角色ID */
|
||||
private Long roleId;
|
||||
|
||||
/** 部门ID */
|
||||
private Long deptId;
|
||||
|
||||
public Long getRoleId()
|
||||
{
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(Long roleId)
|
||||
{
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public Long getDeptId()
|
||||
{
|
||||
return deptId;
|
||||
}
|
||||
|
||||
public void setDeptId(Long deptId)
|
||||
{
|
||||
this.deptId = deptId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("roleId", getRoleId())
|
||||
.append("deptId", getDeptId())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
/**
|
||||
* 角色和菜单关联 sys_role_menu
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SysRoleMenu
|
||||
{
|
||||
/** 角色ID */
|
||||
private Long roleId;
|
||||
|
||||
/** 菜单ID */
|
||||
private Long menuId;
|
||||
|
||||
public Long getRoleId()
|
||||
{
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(Long roleId)
|
||||
{
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
public Long getMenuId()
|
||||
{
|
||||
return menuId;
|
||||
}
|
||||
|
||||
public void setMenuId(Long menuId)
|
||||
{
|
||||
this.menuId = menuId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("roleId", getRoleId())
|
||||
.append("menuId", getMenuId())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.lingniu.idp.common.xss.Xss;
|
||||
import org.lingniu.idp.model.base.BaseEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户对象 sys_user
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class SysUser extends BaseEntity
|
||||
{
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 用户ID */
|
||||
private Long userId;
|
||||
|
||||
/** 部门ID */
|
||||
private Long deptId;
|
||||
|
||||
/** 用户账号 */
|
||||
@Xss(message = "用户账号不能包含脚本字符")
|
||||
@NotBlank(message = "用户账号不能为空")
|
||||
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
|
||||
private String userName;
|
||||
|
||||
/** 用户昵称 */
|
||||
@Xss(message = "用户昵称不能包含脚本字符")
|
||||
@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
|
||||
private String nickName;
|
||||
|
||||
/** 用户邮箱 */
|
||||
@Email(message = "邮箱格式不正确")
|
||||
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
|
||||
private String email;
|
||||
|
||||
/** 手机号码 */
|
||||
@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
|
||||
private String phonenumber;
|
||||
|
||||
/** 用户性别 */
|
||||
private String sex;
|
||||
|
||||
/** 用户头像 */
|
||||
private String avatar;
|
||||
|
||||
/** 密码 */
|
||||
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
|
||||
private String password;
|
||||
|
||||
/** 账号状态(0正常 1停用) */
|
||||
private String status;
|
||||
|
||||
/** 删除标志(0代表存在 2代表删除) */
|
||||
private String delFlag;
|
||||
|
||||
/** 最后登录IP */
|
||||
private String loginIp;
|
||||
|
||||
/** 最后登录时间 */
|
||||
private Date loginDate;
|
||||
|
||||
/** 密码最后更新时间 */
|
||||
private Date pwdUpdateDate;
|
||||
|
||||
private SysDept dept;
|
||||
private List<SysDept> deptList;
|
||||
private List<SysPost> posts;
|
||||
|
||||
/** 角色对象 */
|
||||
private List<SysRole> roles;
|
||||
|
||||
/** 角色组 */
|
||||
private Long[] roleIds;
|
||||
|
||||
/** 岗位组 */
|
||||
private Long[] postIds;
|
||||
|
||||
/** 角色ID */
|
||||
private Long roleId;
|
||||
public SysUser(Long userId){
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public boolean isAdmin(){
|
||||
return userId!=null && userId==1;
|
||||
}
|
||||
public static boolean isAdmin(Long userId){
|
||||
return userId!=null && userId==1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("userId", getUserId())
|
||||
.append("deptId", getDeptId())
|
||||
.append("userName", getUserName())
|
||||
.append("nickName", getNickName())
|
||||
.append("email", getEmail())
|
||||
.append("phonenumber", getPhonenumber())
|
||||
.append("sex", getSex())
|
||||
.append("avatar", getAvatar())
|
||||
.append("password", getPassword())
|
||||
.append("status", getStatus())
|
||||
.append("delFlag", getDelFlag())
|
||||
.append("loginIp", getLoginIp())
|
||||
.append("loginDate", getLoginDate())
|
||||
.append("pwdUpdateDate", getPwdUpdateDate())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("remark", getRemark())
|
||||
.append("dept", getDept())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
/**
|
||||
* 当前在线会话
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SysUserOnline
|
||||
{
|
||||
/** 会话编号 */
|
||||
private String tokenId;
|
||||
|
||||
/** 部门名称 */
|
||||
private String deptName;
|
||||
|
||||
/** 用户名称 */
|
||||
private String userName;
|
||||
|
||||
/** 登录IP地址 */
|
||||
private String ipaddr;
|
||||
|
||||
/** 登录地址 */
|
||||
private String loginLocation;
|
||||
|
||||
/** 浏览器类型 */
|
||||
private String browser;
|
||||
|
||||
/** 操作系统 */
|
||||
private String os;
|
||||
|
||||
/** 登录时间 */
|
||||
private Long loginTime;
|
||||
|
||||
public String getTokenId()
|
||||
{
|
||||
return tokenId;
|
||||
}
|
||||
|
||||
public void setTokenId(String tokenId)
|
||||
{
|
||||
this.tokenId = tokenId;
|
||||
}
|
||||
|
||||
public String getDeptName()
|
||||
{
|
||||
return deptName;
|
||||
}
|
||||
|
||||
public void setDeptName(String deptName)
|
||||
{
|
||||
this.deptName = deptName;
|
||||
}
|
||||
|
||||
public String getUserName()
|
||||
{
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName)
|
||||
{
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getIpaddr()
|
||||
{
|
||||
return ipaddr;
|
||||
}
|
||||
|
||||
public void setIpaddr(String ipaddr)
|
||||
{
|
||||
this.ipaddr = ipaddr;
|
||||
}
|
||||
|
||||
public String getLoginLocation()
|
||||
{
|
||||
return loginLocation;
|
||||
}
|
||||
|
||||
public void setLoginLocation(String loginLocation)
|
||||
{
|
||||
this.loginLocation = loginLocation;
|
||||
}
|
||||
|
||||
public String getBrowser()
|
||||
{
|
||||
return browser;
|
||||
}
|
||||
|
||||
public void setBrowser(String browser)
|
||||
{
|
||||
this.browser = browser;
|
||||
}
|
||||
|
||||
public String getOs()
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
public void setOs(String os)
|
||||
{
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
public Long getLoginTime()
|
||||
{
|
||||
return loginTime;
|
||||
}
|
||||
|
||||
public void setLoginTime(Long loginTime)
|
||||
{
|
||||
this.loginTime = loginTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
/**
|
||||
* 用户和岗位关联 sys_user_post
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SysUserPost
|
||||
{
|
||||
/** 用户ID */
|
||||
private Long userId;
|
||||
|
||||
/** 岗位ID */
|
||||
private Long postId;
|
||||
|
||||
public Long getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getPostId()
|
||||
{
|
||||
return postId;
|
||||
}
|
||||
|
||||
public void setPostId(Long postId)
|
||||
{
|
||||
this.postId = postId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("userId", getUserId())
|
||||
.append("postId", getPostId())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.lingniu.idp.model.entity;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
/**
|
||||
* 用户和角色关联 sys_user_role
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class SysUserRole
|
||||
{
|
||||
/** 用户ID */
|
||||
private Long userId;
|
||||
|
||||
/** 角色ID */
|
||||
private Long roleId;
|
||||
|
||||
public Long getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getRoleId()
|
||||
{
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public void setRoleId(Long roleId)
|
||||
{
|
||||
this.roleId = roleId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("userId", getUserId())
|
||||
.append("roleId", getRoleId())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
package org.lingniu.idp.model.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.lingniu.idp.enums.DeviceType;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Access Token 信息
|
||||
* 存储在 Redis String 结构中
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AccessTokenInfo {
|
||||
private String tokenValue;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* 权限范围
|
||||
*/
|
||||
private Set<String> scopes;
|
||||
|
||||
/**
|
||||
* 颁发时间
|
||||
*/
|
||||
private Instant issuedAt;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Instant expiresAt;
|
||||
|
||||
/**
|
||||
* 设备ID(可选,用于设备管理)
|
||||
*/
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 设备类型(WEB/IOS/ANDROID)
|
||||
*/
|
||||
private DeviceType deviceType;
|
||||
|
||||
/**
|
||||
* IP地址
|
||||
*/
|
||||
private String ipAddress;
|
||||
|
||||
/**
|
||||
* 用户代理(User-Agent)
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* 是否已撤销
|
||||
*/
|
||||
private boolean revoked;
|
||||
|
||||
/**
|
||||
* 撤销时间
|
||||
*/
|
||||
private Instant revokedAt;
|
||||
|
||||
/**
|
||||
* 关联的刷新Token ID
|
||||
*/
|
||||
private String refreshTokenId;
|
||||
|
||||
/**
|
||||
* JWT ID(如果是JWT token)
|
||||
*/
|
||||
private String jti;
|
||||
|
||||
/**
|
||||
* 附加数据(JSON格式)
|
||||
*/
|
||||
private String additionalInfo;
|
||||
|
||||
/**
|
||||
* 检查Token是否过期
|
||||
*/
|
||||
public boolean isExpired() {
|
||||
return expiresAt != null && Instant.now().isAfter(expiresAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Token是否有效
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return !isExpired() && !revoked;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取剩余有效时间(秒)
|
||||
*/
|
||||
public long getRemainingSeconds() {
|
||||
if (expiresAt == null) {
|
||||
return 0;
|
||||
}
|
||||
Instant now = Instant.now();
|
||||
if (now.isAfter(expiresAt)) {
|
||||
return 0;
|
||||
}
|
||||
return expiresAt.getEpochSecond() - now.getEpochSecond();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Token使用时长(秒)
|
||||
*/
|
||||
public long getUsedSeconds() {
|
||||
if (issuedAt == null) {
|
||||
return 0;
|
||||
}
|
||||
Instant end = revoked ? (revokedAt != null ? revokedAt : Instant.now()) : Instant.now();
|
||||
return end.getEpochSecond() - issuedAt.getEpochSecond();
|
||||
}
|
||||
public Map<String, String> toRevokeMap() {
|
||||
Map<String, String> hash = new HashMap<>();
|
||||
hash.put("revoked", Boolean.toString(revoked));
|
||||
hash.put("revokedAt", revokedAt != null ? revokedAt.toString() : "");
|
||||
return hash;
|
||||
}
|
||||
/**
|
||||
* 转换为Map,便于Redis存储
|
||||
*/
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("userId", userId);
|
||||
map.put("username", username);
|
||||
map.put("clientId", clientId);
|
||||
map.put("tokenValue",tokenValue);
|
||||
map.put("scopes", scopes != null ? String.join(",", scopes) : "");
|
||||
map.put("issuedAt", issuedAt != null ? issuedAt.toString() : null);
|
||||
map.put("expiresAt", expiresAt != null ? expiresAt.toString() : null);
|
||||
map.put("deviceId", deviceId);
|
||||
map.put("deviceType", deviceType != null ? deviceType.name() : null);
|
||||
map.put("ipAddress", ipAddress);
|
||||
map.put("userAgent", userAgent);
|
||||
map.put("revoked", Boolean.toString(revoked));
|
||||
map.put("revokedAt", revokedAt != null ? revokedAt.toString() : null);
|
||||
map.put("refreshTokenId", refreshTokenId);
|
||||
map.put("jti", jti);
|
||||
map.put("additionalInfo", additionalInfo);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Map创建AccessTokenInfo
|
||||
*/
|
||||
public static AccessTokenInfo fromMap(Map<String, Object> map) {
|
||||
if (map == null || map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AccessTokenInfo.AccessTokenInfoBuilder builder = AccessTokenInfo.builder();
|
||||
|
||||
builder.userId((String) map.get("userId"));
|
||||
builder.username((String) map.get("username"));
|
||||
builder.clientId((String) map.get("clientId"));
|
||||
builder.tokenValue((String) map.get("tokenValue"));
|
||||
|
||||
// 处理scopes
|
||||
String scopesStr = (String) map.get("scopes");
|
||||
if (scopesStr != null && !scopesStr.isEmpty()) {
|
||||
builder.scopes(new HashSet<>(Arrays.asList(scopesStr.split(","))));
|
||||
}
|
||||
|
||||
// 处理时间字段
|
||||
String issuedAtStr = (String) map.get("issuedAt");
|
||||
if (issuedAtStr != null) {
|
||||
builder.issuedAt(Instant.parse(issuedAtStr));
|
||||
}
|
||||
|
||||
String expiresAtStr = (String) map.get("expiresAt");
|
||||
if (expiresAtStr != null) {
|
||||
builder.expiresAt(Instant.parse(expiresAtStr));
|
||||
}
|
||||
|
||||
builder.deviceId((String) map.get("deviceId"));
|
||||
|
||||
// 处理deviceType
|
||||
String deviceTypeStr = (String) map.get("deviceType");
|
||||
if (deviceTypeStr != null) {
|
||||
try {
|
||||
builder.deviceType(DeviceType.valueOf(deviceTypeStr));
|
||||
} catch (IllegalArgumentException e) {
|
||||
builder.deviceType(DeviceType.OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
builder.ipAddress((String) map.get("ipAddress"));
|
||||
builder.userAgent((String) map.get("userAgent"));
|
||||
|
||||
// 处理布尔值
|
||||
String revokedStr = (String) map.get("revoked");
|
||||
if (revokedStr != null) {
|
||||
builder.revoked(Boolean.parseBoolean(revokedStr));
|
||||
}
|
||||
|
||||
String revokedAtStr = (String) map.get("revokedAt");
|
||||
if (revokedAtStr != null) {
|
||||
builder.revokedAt(Instant.parse(revokedAtStr));
|
||||
}
|
||||
|
||||
builder.refreshTokenId((String) map.get("refreshTokenId"));
|
||||
builder.jti((String) map.get("jti"));
|
||||
builder.additionalInfo((String) map.get("additionalInfo"));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 简化的用户信息(用于接口返回)
|
||||
*/
|
||||
public Map<String, Object> toSimpleInfo() {
|
||||
Map<String, Object> info = new HashMap<>();
|
||||
info.put("userId", userId);
|
||||
info.put("username", username);
|
||||
info.put("clientId", clientId);
|
||||
info.put("scopes", scopes);
|
||||
info.put("expiresAt", expiresAt != null ? expiresAt.toEpochMilli() : null);
|
||||
info.put("issuedAt", issuedAt != null ? issuedAt.toEpochMilli() : null);
|
||||
info.put("deviceType", deviceType != null ? deviceType.name() : null);
|
||||
info.put("valid", isValid());
|
||||
return info;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.lingniu.idp.model.vo;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class DataPermission {
|
||||
/** 允许全部*/
|
||||
private boolean allowAll;
|
||||
/**仅自己*/
|
||||
private boolean onlySelf;
|
||||
/**部门列表*/
|
||||
private Set<String> deptList;
|
||||
/**地区*/
|
||||
private Set<String> areas;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package org.lingniu.idp.model.vo;
|
||||
|
||||
|
||||
import org.lingniu.idp.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 路由显示信息
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
public class MetaVo
|
||||
{
|
||||
/**
|
||||
* 设置该路由在侧边栏和面包屑中展示的名字
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 设置该路由的图标,对应路径src/assets/icons/svg
|
||||
*/
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 设置为true,则不会被 <keep-alive>缓存
|
||||
*/
|
||||
private boolean noCache;
|
||||
|
||||
/**
|
||||
* 内链地址(http(s)://开头)
|
||||
*/
|
||||
private String link;
|
||||
|
||||
public MetaVo()
|
||||
{
|
||||
}
|
||||
|
||||
public MetaVo(String title, String icon)
|
||||
{
|
||||
this.title = title;
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public MetaVo(String title, String icon, boolean noCache)
|
||||
{
|
||||
this.title = title;
|
||||
this.icon = icon;
|
||||
this.noCache = noCache;
|
||||
}
|
||||
|
||||
public MetaVo(String title, String icon, String link)
|
||||
{
|
||||
this.title = title;
|
||||
this.icon = icon;
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
public MetaVo(String title, String icon, boolean noCache, String link)
|
||||
{
|
||||
this.title = title;
|
||||
this.icon = icon;
|
||||
this.noCache = noCache;
|
||||
if (StringUtils.ishttp(link))
|
||||
{
|
||||
this.link = link;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNoCache()
|
||||
{
|
||||
return noCache;
|
||||
}
|
||||
|
||||
public void setNoCache(boolean noCache)
|
||||
{
|
||||
this.noCache = noCache;
|
||||
}
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getIcon()
|
||||
{
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void setIcon(String icon)
|
||||
{
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public String getLink()
|
||||
{
|
||||
return link;
|
||||
}
|
||||
|
||||
public void setLink(String link)
|
||||
{
|
||||
this.link = link;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,436 @@
|
||||
package org.lingniu.idp.model.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.lingniu.idp.enums.DeviceType;
|
||||
import org.lingniu.idp.enums.RevokeReason;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Refresh Token 信息
|
||||
* 存储在 Redis Hash 结构中
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RefreshTokenInfo {
|
||||
private String tokenValue;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 客户端ID
|
||||
*/
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* 设备ID(唯一标识设备)
|
||||
*/
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 设备名称(用户自定义)
|
||||
*/
|
||||
private String deviceName;
|
||||
|
||||
/**
|
||||
* 设备类型
|
||||
*/
|
||||
private DeviceType deviceType;
|
||||
|
||||
/**
|
||||
* 操作系统
|
||||
*/
|
||||
private String operatingSystem;
|
||||
|
||||
/**
|
||||
* 浏览器/客户端类型
|
||||
*/
|
||||
private String clientType;
|
||||
|
||||
/**
|
||||
* 权限范围
|
||||
*/
|
||||
private Set<String> scopes;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Instant createdAt;
|
||||
|
||||
/**
|
||||
* 最后使用时间
|
||||
*/
|
||||
private Instant lastUsedAt;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*/
|
||||
private Instant expiresAt;
|
||||
|
||||
/**
|
||||
* IP地址(创建时的IP)
|
||||
*/
|
||||
private String ipAddress;
|
||||
|
||||
/**
|
||||
* 用户代理(创建时的User-Agent)
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* 是否已撤销
|
||||
*/
|
||||
private boolean revoked;
|
||||
|
||||
/**
|
||||
* 撤销时间
|
||||
*/
|
||||
private Instant revokedAt;
|
||||
|
||||
/**
|
||||
* 撤销原因
|
||||
*/
|
||||
private RevokeReason revokeReason;
|
||||
/**
|
||||
* 对应accessToken
|
||||
*/
|
||||
private String accessToken;
|
||||
/**
|
||||
* 关联的Access Token数量(用于统计)
|
||||
*/
|
||||
private int accessTokenCount;
|
||||
|
||||
/**
|
||||
* 使用次数
|
||||
*/
|
||||
private int usageCount;
|
||||
|
||||
/**
|
||||
* 地理位置信息(可选)
|
||||
*/
|
||||
private String location;
|
||||
|
||||
/**
|
||||
* 附加数据(JSON格式)
|
||||
*/
|
||||
private String additionalInfo;
|
||||
|
||||
/**
|
||||
* 是否记住登录
|
||||
*/
|
||||
private boolean rememberMe;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 检查Refresh Token是否过期
|
||||
*/
|
||||
public boolean isExpired() {
|
||||
return expiresAt != null && Instant.now().isAfter(expiresAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Refresh Token是否有效
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return !isExpired() && !revoked;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取剩余有效时间(秒)
|
||||
*/
|
||||
public long getRemainingSeconds() {
|
||||
if (expiresAt == null) {
|
||||
return 0;
|
||||
}
|
||||
Instant now = Instant.now();
|
||||
if (now.isAfter(expiresAt)) {
|
||||
return 0;
|
||||
}
|
||||
return expiresAt.getEpochSecond() - now.getEpochSecond();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取活跃天数(创建到现在)
|
||||
*/
|
||||
public long getActiveDays() {
|
||||
if (createdAt == null) {
|
||||
return 0;
|
||||
}
|
||||
Instant end = revoked ? (revokedAt != null ? revokedAt : Instant.now()) : Instant.now();
|
||||
long seconds = end.getEpochSecond() - createdAt.getEpochSecond();
|
||||
return seconds / (24 * 3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取闲置天数(最后使用到现在)
|
||||
*/
|
||||
public long getIdleDays() {
|
||||
if (lastUsedAt == null) {
|
||||
return getActiveDays();
|
||||
}
|
||||
Instant now = Instant.now();
|
||||
long seconds = now.getEpochSecond() - lastUsedAt.getEpochSecond();
|
||||
return seconds / (24 * 3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加使用计数
|
||||
*/
|
||||
public void incrementUsage() {
|
||||
this.usageCount++;
|
||||
this.lastUsedAt = Instant.now();
|
||||
}
|
||||
|
||||
public void incrementAccessTokenUsage(String accessToken) {
|
||||
this.accessTokenCount++;
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销Token
|
||||
*/
|
||||
public void revoke(RevokeReason reason) {
|
||||
this.revoked = true;
|
||||
this.revokedAt = Instant.now();
|
||||
this.revokeReason = reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Map,便于Redis存储
|
||||
*/
|
||||
public Map<String, String> toMap() {
|
||||
Map<String, String> hash = new HashMap<>();
|
||||
|
||||
hash.put("userId", userId != null ? userId : "");
|
||||
hash.put("username", username != null ? username : "");
|
||||
hash.put("clientId", clientId != null ? clientId : "");
|
||||
hash.put("deviceId", deviceId != null ? deviceId : "");
|
||||
hash.put("tokenValue", tokenValue != null ? tokenValue : "");
|
||||
hash.put("deviceName", deviceName != null ? deviceName : "");
|
||||
hash.put("deviceType", deviceType != null ? deviceType.name() : DeviceType.OTHER.name());
|
||||
hash.put("operatingSystem", operatingSystem != null ? operatingSystem : "");
|
||||
hash.put("clientType", clientType != null ? clientType : "");
|
||||
hash.put("accessToken", accessToken != null ? accessToken : "");
|
||||
hash.put("scopes", scopes != null ? String.join(",", scopes) : "");
|
||||
hash.put("createdAt", createdAt != null ? createdAt.toString() : "");
|
||||
hash.put("lastUsedAt", lastUsedAt != null ? lastUsedAt.toString() : "");
|
||||
hash.put("expiresAt", expiresAt != null ? expiresAt.toString() : "");
|
||||
hash.put("ipAddress", ipAddress != null ? ipAddress : "");
|
||||
hash.put("userAgent", userAgent != null ? userAgent : "");
|
||||
hash.put("revoked", Boolean.toString(revoked));
|
||||
hash.put("revokedAt", revokedAt != null ? revokedAt.toString() : "");
|
||||
hash.put("revokeReason", revokeReason != null ? revokeReason.name() : "");
|
||||
hash.put("accessTokenCount", Integer.toString(accessTokenCount));
|
||||
hash.put("usageCount", Integer.toString(usageCount));
|
||||
hash.put("location", location != null ? location : "");
|
||||
hash.put("additionalInfo", additionalInfo != null ? additionalInfo : "");
|
||||
hash.put("rememberMe", Boolean.toString(rememberMe));
|
||||
|
||||
return hash;
|
||||
}
|
||||
public Map<String, String> toUpdateMap() {
|
||||
Map<String, String> hash = new HashMap<>();
|
||||
hash.put("lastUsedAt", lastUsedAt != null ? lastUsedAt.toString() : "");
|
||||
hash.put("accessTokenCount", Integer.toString(accessTokenCount));
|
||||
hash.put("accessToken", accessToken != null ? accessToken : "");
|
||||
hash.put("usageCount", Integer.toString(usageCount));
|
||||
return hash;
|
||||
}
|
||||
public Map<String, String> toRevokeMap() {
|
||||
Map<String, String> hash = new HashMap<>();
|
||||
hash.put("revoked", Boolean.toString(revoked));
|
||||
hash.put("revokedAt", revokedAt != null ? revokedAt.toString() : "");
|
||||
hash.put("revokeReason", revokeReason != null ? revokeReason.name() : "");
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Redis Hash创建RefreshTokenInfo
|
||||
*/
|
||||
public static RefreshTokenInfo fromMap(Map<String, Object> hash) {
|
||||
if (hash == null || hash.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
RefreshTokenInfoBuilder builder = RefreshTokenInfo.builder();
|
||||
|
||||
builder.userId((String) hash.getOrDefault("userId", ""));
|
||||
builder.username((String) hash.getOrDefault("username", ""));
|
||||
builder.clientId((String) hash.getOrDefault("clientId", ""));
|
||||
builder.deviceId((String) hash.getOrDefault("deviceId", ""));
|
||||
builder.deviceName((String) hash.getOrDefault("deviceName", ""));
|
||||
builder.accessToken((String) hash.getOrDefault("accessToken", ""));
|
||||
builder.tokenValue((String) hash.getOrDefault("tokenValue", ""));
|
||||
|
||||
// 处理deviceType
|
||||
String deviceTypeStr = (String)hash.get("deviceType");
|
||||
if (deviceTypeStr != null && !deviceTypeStr.isEmpty()) {
|
||||
try {
|
||||
builder.deviceType(DeviceType.valueOf(deviceTypeStr));
|
||||
} catch (IllegalArgumentException e) {
|
||||
builder.deviceType(DeviceType.OTHER);
|
||||
}
|
||||
} else {
|
||||
builder.deviceType(DeviceType.OTHER);
|
||||
}
|
||||
|
||||
builder.operatingSystem((String) hash.getOrDefault("operatingSystem", ""));
|
||||
builder.clientType((String) hash.getOrDefault("clientType", ""));
|
||||
|
||||
// 处理scopes
|
||||
String scopesStr = (String)hash.get("scopes");
|
||||
if (scopesStr != null && !scopesStr.isEmpty()) {
|
||||
builder.scopes(new HashSet<>(Arrays.asList(scopesStr.split(","))));
|
||||
} else {
|
||||
builder.scopes(new HashSet<>());
|
||||
}
|
||||
|
||||
// 处理时间字段
|
||||
String createdAtStr = (String)hash.get("createdAt");
|
||||
if (createdAtStr != null && !createdAtStr.isEmpty()) {
|
||||
try {
|
||||
builder.createdAt(Instant.parse(createdAtStr));
|
||||
} catch (Exception e) {
|
||||
// 解析失败,使用当前时间
|
||||
builder.createdAt(Instant.now());
|
||||
}
|
||||
}
|
||||
|
||||
String lastUsedAtStr = (String)hash.get("lastUsedAt");
|
||||
if (lastUsedAtStr != null && !lastUsedAtStr.isEmpty()) {
|
||||
try {
|
||||
builder.lastUsedAt(Instant.parse(lastUsedAtStr));
|
||||
} catch (Exception e) {
|
||||
// 解析失败,忽略
|
||||
}
|
||||
}
|
||||
|
||||
String expiresAtStr = (String)hash.get("expiresAt");
|
||||
if (expiresAtStr != null && !expiresAtStr.isEmpty()) {
|
||||
try {
|
||||
builder.expiresAt(Instant.parse(expiresAtStr));
|
||||
} catch (Exception e) {
|
||||
// 解析失败,忽略
|
||||
}
|
||||
}
|
||||
|
||||
builder.ipAddress((String) hash.getOrDefault("ipAddress", ""));
|
||||
builder.userAgent((String) hash.getOrDefault("userAgent", ""));
|
||||
|
||||
// 处理布尔值
|
||||
String revokedStr = (String)hash.get("revoked");
|
||||
builder.revoked(Boolean.parseBoolean(revokedStr));
|
||||
|
||||
String revokedAtStr = (String)hash.get("revokedAt");
|
||||
if (revokedAtStr != null && !revokedAtStr.isEmpty()) {
|
||||
try {
|
||||
builder.revokedAt(Instant.parse(revokedAtStr));
|
||||
} catch (Exception e) {
|
||||
// 解析失败,忽略
|
||||
}
|
||||
}
|
||||
|
||||
// 处理撤销原因
|
||||
String revokeReasonStr = (String)hash.get("revokeReason");
|
||||
if (revokeReasonStr != null && !revokeReasonStr.isEmpty()) {
|
||||
try {
|
||||
builder.revokeReason(RevokeReason.valueOf(revokeReasonStr));
|
||||
} catch (IllegalArgumentException e) {
|
||||
builder.revokeReason(RevokeReason.OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理数值字段
|
||||
String accessTokenCountStr = (String)hash.get("accessTokenCount");
|
||||
if (accessTokenCountStr != null && !accessTokenCountStr.isEmpty()) {
|
||||
try {
|
||||
builder.accessTokenCount(Integer.parseInt(accessTokenCountStr));
|
||||
} catch (NumberFormatException e) {
|
||||
builder.accessTokenCount(0);
|
||||
}
|
||||
}
|
||||
|
||||
String usageCountStr = (String)hash.get("usageCount");
|
||||
if (usageCountStr != null && !usageCountStr.isEmpty()) {
|
||||
try {
|
||||
builder.usageCount(Integer.parseInt(usageCountStr));
|
||||
} catch (NumberFormatException e) {
|
||||
builder.usageCount(0);
|
||||
}
|
||||
}
|
||||
|
||||
builder.location((String) hash.getOrDefault("location", ""));
|
||||
builder.additionalInfo((String) hash.getOrDefault("additionalInfo", ""));
|
||||
|
||||
String rememberMeStr = (String)hash.get("rememberMe");
|
||||
builder.rememberMe(Boolean.parseBoolean(rememberMeStr));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 简化的设备信息(用于前端展示)
|
||||
*/
|
||||
public Map<String, Object> toSimpleDeviceInfo() {
|
||||
Map<String, Object> info = new HashMap<>();
|
||||
info.put("deviceId", deviceId);
|
||||
info.put("deviceName", deviceName);
|
||||
info.put("deviceType", deviceType != null ? deviceType.name() : null);
|
||||
info.put("deviceTypeDesc", deviceType != null ? deviceType.getDescription() : null);
|
||||
info.put("operatingSystem", operatingSystem);
|
||||
info.put("clientType", clientType);
|
||||
info.put("ipAddress", ipAddress);
|
||||
info.put("location", location);
|
||||
info.put("createdAt", createdAt != null ? createdAt.toEpochMilli() : null);
|
||||
info.put("lastUsedAt", lastUsedAt != null ? lastUsedAt.toEpochMilli() : null);
|
||||
info.put("active", !revoked && !isExpired());
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可读的设备信息
|
||||
*/
|
||||
public String getReadableDeviceInfo() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (deviceName != null && !deviceName.isEmpty()) {
|
||||
sb.append(deviceName);
|
||||
} else if (deviceType != null) {
|
||||
sb.append(deviceType.getDescription());
|
||||
}
|
||||
|
||||
if (operatingSystem != null && !operatingSystem.isEmpty()) {
|
||||
sb.append(" (").append(operatingSystem);
|
||||
if (clientType != null && !clientType.isEmpty()) {
|
||||
sb.append(" - ").append(clientType);
|
||||
}
|
||||
sb.append(")");
|
||||
} else if (clientType != null && !clientType.isEmpty()) {
|
||||
sb.append(" (").append(clientType).append(")");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package org.lingniu.idp.model.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 路由配置信息
|
||||
*
|
||||
* @author portal
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public class RouterVo
|
||||
{
|
||||
/**
|
||||
* 路由名字
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 路由地址
|
||||
*/
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现
|
||||
*/
|
||||
private boolean hidden;
|
||||
|
||||
/**
|
||||
* 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
|
||||
*/
|
||||
private String redirect;
|
||||
|
||||
/**
|
||||
* 组件地址
|
||||
*/
|
||||
private String component;
|
||||
|
||||
/**
|
||||
* 路由参数:如 {"id": 1, "name": "admin"}
|
||||
*/
|
||||
private String query;
|
||||
|
||||
/**
|
||||
* 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
|
||||
*/
|
||||
private Boolean alwaysShow;
|
||||
|
||||
/**
|
||||
* 其他元素
|
||||
*/
|
||||
private MetaVo meta;
|
||||
|
||||
/**
|
||||
* 子路由
|
||||
*/
|
||||
private List<RouterVo> children;
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path)
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public boolean getHidden()
|
||||
{
|
||||
return hidden;
|
||||
}
|
||||
|
||||
public void setHidden(boolean hidden)
|
||||
{
|
||||
this.hidden = hidden;
|
||||
}
|
||||
|
||||
public String getRedirect()
|
||||
{
|
||||
return redirect;
|
||||
}
|
||||
|
||||
public void setRedirect(String redirect)
|
||||
{
|
||||
this.redirect = redirect;
|
||||
}
|
||||
|
||||
public String getComponent()
|
||||
{
|
||||
return component;
|
||||
}
|
||||
|
||||
public void setComponent(String component)
|
||||
{
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
public String getQuery()
|
||||
{
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(String query)
|
||||
{
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public Boolean getAlwaysShow()
|
||||
{
|
||||
return alwaysShow;
|
||||
}
|
||||
|
||||
public void setAlwaysShow(Boolean alwaysShow)
|
||||
{
|
||||
this.alwaysShow = alwaysShow;
|
||||
}
|
||||
|
||||
public MetaVo getMeta()
|
||||
{
|
||||
return meta;
|
||||
}
|
||||
|
||||
public void setMeta(MetaVo meta)
|
||||
{
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
public List<RouterVo> getChildren()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<RouterVo> children)
|
||||
{
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user