apache shiro

这是致力于Apache Shiro的系列文章的第二部分。 我们从简单的不安全Web应用程序开始了上一部分 。 完成后,该应用程序具有基本的身份验证和授权。 用户可以登录和注销。 所有网页和按钮均已分配并实施了访问权限。 授权和身份验证数据都已存储在静态配置文件中。

正如我们在最后一部分中承诺的,我们将用户帐户数据移至数据库。 另外,我们将为用户提供通过PGP证书进行身份验证的选项。 因此,我们的应用程序将具有多个备用登录选项:使用用户名/密码登录和使用证书登录。 最后,我们将强制启用备用登录选项。

换句话说,我们将展示如何创建自定义领域以及如何处理多领域方案。 我们将创建三个不同版本的SimpleShiroSecuredApplication:

  • 版本,并将所有帐户信息移至数据库 ,
  • 允许PGP证书作为替代身份验证机制的版本 ,
  • 需要同时输入用户名/密码和PGP证书的版本 。

每个版本都有测试类RunWaitTest。 该类使用在http:// localhost:9180 / simpleshirosecuredapplication / url上部署的应用程序启动Web服务器。

注意:自第一版以来,我们更新了上一部分。 最显着的变化是新部分 ,该部分显示了如何向登录页面添加错误消息。 感谢大家的反馈。

境界

首先,我们解释什么是领域以及如何创建它们。 如果您对理论不感兴趣,请继续下一章 。
领域负责身份验证和授权。 每当用户想要登录到应用程序时,都会收集身份验证信息并将其传递到领域。 Realm验证提供的数据并决定是否应允许用户登录,访问资源或拥有特定角色。
认证信息包括两个部分:

  • 主体–代表帐户唯一标识符,例如用户名,帐户ID,PGP证书等。
  • 凭证–证明用户身份,例如密码,PGP证书,指纹等。

Shiro提供了能够从活动目录 , ldap , ini文件 , 属性文件和数据库中读取授权数据的领域。 在Shiro.ini文件的主要部分中配置领域:

realmName=org.apache.shiro.realm.jdbc.JdbcRealm

认证方式

所有领域都实现Realm接口。 有两种重要的接口方法:supports和getAuthenticationInfo。 两者都在身份验证令牌对象中接收主体和凭据。
支持方法根据提供的身份验证令牌确定领域是否能够对用户进行身份验证。 例如,如果我的领域检查用户名和密码,则仅使用X509证书拒绝身份验证令牌。
方法getAuthenticationInfo本身执行身份验证。 如果来自身份验证令牌的主体和凭据表示有效的登录信息,则该方法返回身份验证信息对象。 否则,领域返回null。

授权书

如果该领域还希望进行授权,则必须实现Authorizer接口。 每个Authorizer方法都将主体作为参数,并检查角色或权限。 重要的是要理解,该领域会获得所有授权请求,即使它们来自另一个领域进行了身份验证的用户也是如此。 当然,领域可以决定忽略任何授权请求。
权限以字符串或权限对象的形式提供。 除非有充分的理由,否则请使用WildcardPermissionResolver将字符串转换为权限对象。

其他选择

Shiro框架在运行时调查其他接口的领域。 如果领域实现了它们,则可以使用:

  • 有关用户注销的信息,
  • 有关系统启动的信息,
  • 全局缓存
  • 在配置文件中配置的名称 ,
  • 在权限字符串和权限对象之间配置的转换器 。

这些功能可用于实现其他接口的任何领域。 无需其他配置。
自定义领域

创建新领域的最简单方法是扩展AuthenticatingRealm或AuthorizingRealm类。 它们具有上一节中提到的所有有用接口的合理实现。 如果它们不能满足您的需求,则可以扩展CachingRealm或从头开始创建新领域。

移至数据库

当前版本的SimpleShiroSecuredApplication使用默认领域进行身份验证和授权。 默认领域– IniRealm从配置文件读取用户帐户信息。 这种存储仅对于最简单的应用程序是可接受的。 任何稍微复杂的事情都需要将凭据存储在更好的持久性存储中。
新要求:帐户凭据和访问权限存储在数据库中。 存储的密码经过哈希处理和加盐处理。
在本章中,我们将把应用程序连接到数据库并创建表以存储所有用户帐户数据。 然后,我们将IniRealm替换为能够从数据库和salt密码读取的领域。

数据库基础架构

本节介绍示例应用程序基础结构。 它不包含有关Shiro的信息,因此您可以自由地跳过它 。
示例应用程序以嵌入式模式使用Apache Derby数据库。
我们使用Liquibase进行数据库部署和升级。 它是开源库,用于跟踪,管理和应用数据库更改。 数据库更改(新表,新列,外键)存储在数据库更改日志文件中。 启动后,Liquibase会调查数据库并应用所有新更改。 结果,数据库始终保持一致并且是最新的,而我们却没有付出任何努力。 将对Derby和Liquibase的依赖项添加到SimpleShiroSecuredApplication pom.xml中 :

<dependency><groupid>org.apache.derby</groupid><artifactid>derby</artifactid><version>10.7.1.1</version>
</dependency>
<dependency><groupid>org.liquibase</groupid><artifactid>liquibase-core</artifactid><version>2.0.1</version>
</dependency>

将jndi添加到码头:

<dependency><groupid>org.mortbay.jetty</groupid><artifactid>jetty-naming</artifactid><version>${jetty.version}</version><scope>test</scope>
</dependency>
<dependency><groupid>org.mortbay.jetty</groupid><artifactid>jetty-plus</artifactid><version>${jetty.version}</version><scope>test</scope>
</dependency>

使用数据库结构描述创建db.changelog.xml文件。 它创建用于存储用户,角色和权限的表。 它还用初始数据填充这些表。 我们使用random_salt_value_username作为盐,并使用以下方法创建哈希盐化密码:

public static String simpleSaltedHash(String username, String password) {Sha256Hash sha256Hash = new Sha256Hash(password, (new SimpleByteSource('random_salt_value_' + username)).getBytes());String result = sha256Hash.toHex();System.out.println(username + ' simple salted hash: ' + result);return result;
}

在WEB-INF / jetty-web.xml文件中创建指向derby的数据源:

<configure class='org.mortbay.jetty.webapp.WebAppContext' id='SimpleShiroSecuredApplication'><new class='org.mortbay.jetty.plus.naming.Resource' id='SimpleShiroSecuredApplication'><arg>jdbc/SimpleShiroSecuredApplicationDB</arg><arg><new class='org.apache.derby.jdbc.EmbeddedDataSource'><set name='DatabaseName'>../SimpleShiroSecuredApplicationDatabase</set><set name='createDatabase'>create</set></new></arg></new>
</configure>

在web.xml文件中配置数据源和liquibase:

<resource-ref><description>Derby Connection</description><res-ref-name>jdbc/SimpleShiroSecuredApplicationDB</res-ref-name><res-type>javax.sql.DataSource</res-type><res-auth>Container</res-auth>
</resource-ref><context-param><param-name>liquibase.changelog</param-name><param-value>src/main/resources/db.changelog.xml</param-value>
</context-param><context-param><param-name>liquibase.datasource</param-name><param-value>jdbc/SimpleShiroSecuredApplicationDB</param-value>
</context-param><listener><listener-class>liquibase.integration.servlet.LiquibaseServletListener</listener-class>
</listener>

最后,在启用了jndi的情况下配置为读取jetty-web.xml的jetty在AbstractContainerTest类中。

创建新领域

Shiro提供的JDBCRealm能够执行身份验证和授权。 它使用可配置SQL查询从数据库中读取用户名,密码,权限和角色。 不幸的是,该领域有两个缺点:

  • 它无法从JNDI加载数据源( 未解决的问题 )。
  • 它无法添加密码( 未解决的问题 )。

我们对其进行扩展,并创建新的类JNDIAndSaltAwareJdbcRealm 。 由于所有属性都可以在ini文件中进行配置,因此新属性jndiDataSourceName也将自动进行配置。 只要设置了新属性,该领域就会在JNDI中查找数据源:

protected String jndiDataSourceName;public String getJndiDataSourceName() {return jndiDataSourceName;
}public void setJndiDataSourceName(String jndiDataSourceName) {this.jndiDataSourceName = jndiDataSourceName;this.dataSource = getDataSourceFromJNDI(jndiDataSourceName);
}private DataSource getDataSourceFromJNDI(String jndiDataSourceName) {try {InitialContext ic = new InitialContext();return (DataSource) ic.lookup(jndiDataSourceName);} catch (NamingException e) {log.error('JNDI error while retrieving ' + jndiDataSourceName, e);throw new AuthorizationException(e);}
}

方法doGetAuthenticationInfo从数据库读取帐户身份验证信息,并将其转换为身份验证信息对象。 如果找不到帐户信息,则返回null。 父类AuthenticatingRealm将身份验证信息对象与原始用户提供的数据进行比较。
我们重写doGetAuthenticationInfo以从数据库中读取密码哈希和盐,并将它们存储在身份验证信息对象中:

doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {...// read password hash and salt from db PasswdSalt passwdSalt = getPasswordForUser(username);...// return salted credentialsSimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, passwdSalt.password, getName());info.setCredentialsSalt(new SimpleByteSource(passwdSalt.salt));return info;
}

这里的示例仅包含最重要的代码段。 在Github上有完整课程 。

配置新领域

在Shiro.ini文件中配置领域和jndi名称:

[main]
# realm to be used
saltedJdbcRealm=org.meri.simpleshirosecuredapplication.realm.JNDIAndSaltAwareJdbcRealm
# any object property is automatically configurable in Shiro.ini file
saltedJdbcRealm.jndiDataSourceName=jdbc/SimpleShiroSecuredApplicationDB
# the realm should handle also authorization
saltedJdbcRealm.permissionsLookupEnabled=true

配置SQL查询:

# If not filled, subclasses of JdbcRealm assume 'select password from users where username = ?'
# first result column is password, second result column is salt
saltedJdbcRealm.authenticationQuery = select password, salt from sec_users where name = ?
# If not filled, subclasses of JdbcRealm assume 'select role_name from user_roles where username = ?'
saltedJdbcRealm.userRolesQuery = select role_name from sec_users_roles where user_name = ?
# If not filled, subclasses of JdbcRealm assume 'select permission from roles_permissions where role_name = ?'
saltedJdbcRealm.permissionsQuery = select permission from sec_roles_permissions where role_name = ?

JdbcRealm使用credetials匹配器的方式与IniRealm完全相同:

# password hashing specification
sha256Matcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
sha256Matcher.hashAlgorithmName=SHA-256
saltedJdbcRealm.credentialsMatcher = $sha256Matcher

注意:我们从配置文件中删除了[用户]和[角色]部分。 否则,Shiro将同时使用IniRealm和JdbcRealm。 这将创建超出本章范围的多领域方案。

从用户的角度来看,应用程序的工作方式与以前完全相同。 他可以登录到以前相同的用户帐户。 但是,用户名,密码,盐,权限和角色现在存储在数据库中。

完整的源代码可在Github上的'authentication_stored_in_database'分支中找到。

备用登录–证书

一些系统允许用户登录使用多种身份验证方式。例如,用户可以提供用户名/密码,使用Google帐户,Facebook帐户或其他任何方式登录。 我们将添加与简单应用程序类似的内容。 我们将为用户提供使用PGP证书进行身份验证的选项。
新要求:应用程序支持PGP证书作为替代身份验证机制。 仅当用户不拥有与应用程序帐户关联的有效证书时,才会显示登录屏幕。 如果用户具有有效的已知PGP证书,则会自动登录。
用户尝试登录应用程序时,必须提供身份验证数据。 这些数据由servlet过滤器捕获。 过滤器将数据转换为身份验证令牌,并将令牌传递给领域。 如果任何领域都希望对用户进行身份验证,它将身份验证令牌转换为身份验证信息对象。 如果该领域不希望这样做,那么它将返回null。 开箱即用的Shiro框架过滤器会忽略请求中的PGP证书。 可用的身份验证令牌无法保存它们,并且领域完全不知道PGP证书。 因此,我们必须创建:

  • 身份验证令牌来移动证书,
  • Servlet过滤器能够读取证书,
  • 验证证书并将其与用户帐户匹配的领域。

我们的应用程序将有两个不同的领域。 一种使用名称标识帐户和密码来验证用户身份,另一种使用PGP证书两者都进行。
在开始编码之前,我们必须处理应用程序周围的PGP证书和基础结构。 如果您对设置的PGP证书不感兴趣,

基础设施

当用户访问Web应用程序时,他的Web浏览器可能会将PGP证书的副本发送到Web服务器。 证书由某个证书颁发机构或证书本身(自签名证书)签名。 Web服务器将其信任的证书列表保存在称为truststore的存储中。 如果信任库包含用户证书或对其进行签名的授权证书,则Web服务器将信任用户证书。 受信任的证书将传递到应用程序。
我们会:

  • 为每个用户创建证书,
  • 创建信任库,
  • 配置Web服务器,
  • 将证书与用户帐户关联。

在portecle中创建和管理证书。 SimpleShiroSecuredApplication的示例证书位于src \ test \ resources \ clients目录中。 所有商店和证书都具有通用密码“秘密”。

创建证书

为portecle中的每个用户创建自签名证书:

  • 创建新的jks密钥库:在File-> New Keystore中,选择jks。
  • 生成新证书:工具->生成密钥对。 将密码字段保留为空,证书将继承密钥库的密码。
  • 导出公共证书:选择新证书->右键单击->导出,选择“头证书”。 这将创建.cer文件。
  • 导出私钥和证书:选择新证书->右键单击->导出,选择私钥和证书。 这将创建.p12文件。

.cer文件仅包含公共证书,因此您可以将其提供给任何人。 另一方面,.p12文件包含用户私钥,因此必须保密。 仅将其分发给用户(例如,将其导入浏览器进行测试)。

创建信任库

创建新的信任库并将公共证书.cer文件导入到其中:

  • 在文件->新密钥库中,选择jks。
  • 工具->导入可信证书。

配置Web服务器

Web服务器必须请求证书,并根据信任库验证它们。 无法从Java请求证书。 每个Web服务器的配置都不同。 Github上的Look at AbstractContainerTest类中提供了Jetty配置。

将证书与帐户关联

每个证书由序列号和签署证书的证书颁发机构的名称唯一标识。 我们将它们与用户名和密码一起存储在数据库表中。 数据库更改位于db.changelog.xml文件中,有关新列,请参见changeset 3 ,有关数据初始化,请参见changeset 4 。

认证令牌

身份验证令牌表示身份验证尝试期间的用户数据和凭据。 它必须实现身份验证令牌接口,并保存我们希望在servlet过滤器和领域之间传递的所有数据。
由于我们希望同时使用用户名/密码和证书进行身份验证,因此我们扩展了UsernamePasswordToken类,并向其添加了证书属性。 新的身份验证令牌X509CertificateUsernamePasswordToken实现了新的接口X509CertificateAuthenticationToken ,两者在Github上都可用:

public class X509CertificateUsernamePasswordToken extends UsernamePasswordToken implements X509CertificateAuthenticationToken {private X509Certificate certificate;@Overridepublic X509Certificate getCertificate() {return certificate;}public void setCertificate(X509Certificate certificate) {this.certificate = certificate;}}

Servlet过滤器

Shiro过滤器将用户数据转换为身份验证令牌。 到目前为止,我们使用了FormAuthenticationFilter 。 如果传入的请求来自登录的用户,则过滤器将允许用户进入。如果用户尝试对自己进行身份验证,则过滤器将创建身份验证令牌并将其传递给框架。 否则,它将用户重定向到登录屏幕。
我们的过滤器CertificateOrFormAuthenticationFilter扩展了FormAuthenticationFilter 。

首先,我们必须说服它,不仅具有用户名和密码的请求,而且具有PGP证书的任何请求都可以被视为尝试登录。 其次,我们必须修改过滤器,以在身份验证令牌中发送PGP证书以及用户名和密码。
方法isLoginSubmission确定请求是否表示身份验证尝试:

@Overrideprotected boolean isLoginSubmission(ServletRequest request, ServletResponse response) {return super.isLoginSubmission(request, response) || isCertificateLogInAttempt(request, response);}private boolean isCertificateLogInAttempt(ServletRequest request, ServletResponse response) {return hasCertificate(request) && !getSubject(request, response).isAuthenticated();}private boolean hasCertificate(ServletRequest request) {return null != getCertificate(request);}private X509Certificate getCertificate(ServletRequest request) {X509Certificate[] attribute = (X509Certificate[]) request.getAttribute('javax.servlet.request.X509Certificate');return attribute==null? null : attribute[0];}

方法createToken创建身份验证令牌:

@Overrideprotected AuthenticationToken createToken(String username, String password, ServletRequest request, ServletResponse response) {boolean rememberMe = isRememberMe(request);String host = getHost(request);X509Certificate certificate = getCertificate(request);return createToken(username, password, rememberMe, host, certificate);}protected AuthenticationToken createToken(String username, String password, boolean rememberMe, String host, X509Certificate certificate) {return new X509CertificateUsernamePasswordToken(username, password, rememberMe, host, certificate);}

在配置文件中用CertificateOrFormAuthenticationFilter过滤器替换FormAuthenticationFilter:

[main]
# filter configuration
certificateFilter = org.meri.simpleshirosecuredapplication.servlet.CertificateOrFormAuthenticationFilter
# specify login page
certificateFilter.loginUrl = /simpleshirosecuredapplication/account/login.jsp
# name of request parameter with username; if not present filter assumes 'username'
certificateFilter.usernameParam = user
# name of request parameter with password; if not present filter assumes 'password'
certificateFilter.passwordParam = pass
# does the user wish to be remembered?; if not present filter assumes 'rememberMe'
certificateFilter.rememberMeParam = remember
# redirect after successful login
certificateFilter.successUrl  = /simpleshirosecuredapplication/account/personalaccountpage.jsp

将所有URL重定向到新的过滤器:

[urls]
# force ssl for login page
/simpleshirosecuredapplication/account/login.jsp=ssl[8443], certificateFilter# only users with some roles are allowed to use role-specific pages
/simpleshirosecuredapplication/repairmen/**=certificateFilter, roles[repairman]
/simpleshirosecuredapplication/sales/**=certificateFilter, roles[sales]
/simpleshirosecuredapplication/scientists/**=certificateFilter, roles[scientist]
/simpleshirosecuredapplication/adminarea/**=certificateFilter, roles[Administrator]# enable certificateFilter filter for all application pages
/simpleshirosecuredapplication/**=certificateFilter

自定义领域

我们的新领域将仅负责身份验证。 授权(访问权限)将由JNDIAndSaltAwareJdbcRealm处理。 只要PGP证书将用户身份验证为与用户名/密码相同的帐户,这种配置就起作用。 否则,新领域返回的主要主体必须与JNDIAndSaltAwareJdbcRealm返回的主要主体相同。
我们的领域不需要缓存,也不需要可选接口提供的任何其他服务。 因此,我们只需要实现两个接口:Realm和Nameable。
X509CertificateRealm仅支持带有PGP证书的身份验证令牌:

@Overridepublic boolean supports(AuthenticationToken token) {if (token!=null)return  token instanceof X509CertificateAuthenticationToken;return false;}

方法getAuthentcationInfo负责身份验证。 如果提供的证书有效并且与用户帐户关联,则领域创建身份验证信息对象。 请记住,主要主体必须与JNDIAndSaltAwareJdbcRealm返回的主体相同:

@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// the cast is legal, since Shiro will let in only X509CertificateAuthenticationToken tokensX509CertificateAuthenticationToken certificateToken = (X509CertificateAuthenticationToken) token;X509Certificate certificate = certificateToken.getCertificate();// verify certificateif (!certificateOK(certificate)) {return null;}// the issuer name and serial number uniquely identifies certificateBigInteger serialNumber = certificate.getSerialNumber();String issuerName = certificate.getIssuerDN().getName();// find account associated with certificateString username = findUsernameToCertificate(issuerName, serialNumber);if (username == null) {// return null as no account was foundreturn null;}// sucesfull verification, return authentication inforeturn new SimpleAuthenticationInfo(username, certificate, getName());
}

请注意,该领域具有两个新属性:trustStore和trustStorePassword。 两者都是PGP证书验证所必需的。 与其他任何属性一样,两者都可以在配置文件中进行配置。
将新领域添加到Shiro.ini文件:

[main]
certificateRealm = org.meri.simpleshirosecuredapplication.realm.X509CertificateRealm
certificateRealm.trustStore=src/main/resources/truststore
certificateRealm.trustStorePassword=secret

现在可以使用PGP证书登录到应用程序。 如果证书不可用,则用户名和密码也可以使用。

应用程序源代码在Github上的'certificates_as_alternative_log_in_method'分支中可用。

多个领域

如果配置文件包含多个领域,则将全部使用。 在这种情况下,Shiro尝试使用所有已配置的领域对用户进行身份验证,并将身份验证结果合并在一起。 负责合并的对象称为身份验证策略。 框架提供了三种身份验证策略:

  • 所有成功的策略
  • 至少一项成功的策略 ,
  • 第一个成功的策略 。

默认情况下,使用“至少一个成功的策略”,这非常适合我们的目的。 同样,可以创建自定义身份验证策略。 例如,我们可能要求用户同时提供PGP证书和用户名/密码凭据才能登录。
新要求:用户必须同时提供PGP证书和用户名/密码凭据才能登录。

换句话说,我们需要的策略是:

  • 如果某些领域不支持令牌,则失败,
  • 如果某些领域无法验证用户身份,则失败,
  • 如果两个领域认证不同的主体,则失败。

认证策略是一个实现认证策略接口的对象。 在身份验证尝试之后和之前调用接口方法。 我们从“所有成功策略”(可用的最接近策略)创建“ 主要主体相同的身份验证策略 ”。 在每次领域身份验证尝试之后,我们将比较主体:

@Override
public AuthenticationInfo afterAttempt(...) {validatePrimaryPrincipals(info, aggregate, realm);return super.afterAttempt(realm, token, info, aggregate, t);
}private void validatePrimaryPrincipals(...) {...Object aggregPrincipal = aggregPrincipals.getPrimaryPrincipal();Object infoPrincipal = infoPrincipals.getPrimaryPrincipal();if (!aggregPrincipal.equals(infoPrincipal)) {String message = 'All realms are required to return the same primary principal. Offending realm: ' + realm.getName();log.debug(message);throw new AuthenticationException(message);}
}

身份验证策略在Shiro.ini文件中配置:

# multi-realms strategy
authenticationStrategy=org.meri.simpleshirosecuredapplication.authc.
PrimaryPrincipalSameAuthenticationStrategy
securityManager.authenticator.authenticationStrategy = $authenticationStrategy

最后,我们必须改回CertificateOrFormAuthenticationFilter的isLoginSubmission方法。 现在仅将具有用户名和密码的请求视为登录尝试。 证书不足:

@Override
protected boolean isLoginSubmission(ServletRequest request, ServletResponse response) {return super.isLoginSubmission(request, response);
}

如果立即运行该应用程序,则必须同时使用证书和用户名/密码登录方法。

该版本在Github上的'certificates_as_mandatory_log_in_method'分支中可用。

结束

此部分专用于Shiro领域。 我们创建了三个不同的应用程序版本,所有这些版本都可以在Github上获得。 它们涵盖了基本且可能是最重要的领域功能。

如果您需要了解更多信息,请从此处链接的类开始并阅读其javadocs。 他们写得很好,内容广泛。

参考: Apache Shiro第2部分–我们的JCG合作伙伴 Maria Jurcovicova在This is Stuff博客上获得的领域,数据库和PGP证书 。

翻译自: https://www.javacodegeeks.com/2012/05/apache-shiro-part-2-realms-database-and.html

apache shiro

apache shiro_Apache Shiro第2部分–领域,数据库和PGP证书相关推荐

  1. Apache Shiro第2部分–领域,数据库和PGP证书

    这是致力于Apache Shiro的系列文章的第二部分. 我们从简单的不安全Web应用程序开始了上一部分 . 完成后,该应用程序具有基本的身份验证和授权. 用户可以登录和注销. 所有网页和按钮均已分配 ...

  2. apache shiro_Apache Shiro第3部分–密码学

    apache shiro 除了保护网页和管理访问权限外, Apache Shiro还执行基本的加密任务. 该框架能够: 加密和解密数据, 哈希数据, 生成随机数. Shiro没有实现任何加密算法. 所 ...

  3. apache shiro_Apache Shiro:简化应用程序安全性

    apache shiro 考虑到JAVA已有10多年的历史了,需要在其应用程序中内置身份验证和授权的应用程序开发人员的选择数量之低令人震惊. 在JAVA和J2EE中,JAAS规范是一种尝试解决安全性的 ...

  4. apache shiro_Apache Shiro第1部分–基础

    apache shiro Apache Shiro (最初称为JSecurity)是Java安全框架. 它被接受并于2010年成为Apache顶级项目.它的目标是功能强大且易于使用. 该项目正在积极开 ...

  5. SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例(转)...

    SpringBoot整合mybatis.shiro.redis实现基于数据库的细粒度动态权限管理系统实例 shiro 目录(?)[+] 前言 表结构 maven配置 配置Druid 配置mybatis ...

  6. SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例...

    SpringBoot整合mybatis.shiro.redis实现基于数据库的细粒度动态权限管理系统实例 shiro 目录(?)[+] 1.前言 本文主要介绍使用SpringBoot与shiro实现基 ...

  7. Apache Nifi在Windows环境下搭建伪群集及证书登录

    代码地址如下: http://www.demodashi.com/demo/11986.html 前些时间做了关于Apache Nifi分布式集群的搭建分享,但很多时候要搭建分布式集群机器资源是个问题 ...

  8. 使用Shiro的JdbcRealm实现查询数据库进行身份认证

    场景 Subject认证主体 Subject认证主体包含两个信息: 1.Principals:身份,可以是用户名,邮件,手机号码等,可以用来标识一个登录主体身份. 2.Credentials:凭证,常 ...

  9. java数据集导出excel_使用Apache Poi将结果集从Java数据库导出到Excel

    帮助我坚持这个从结果集导出到excel的项目.此前的解决方案还没有回答我的问题,但是他们帮助了..到目前为止,我的代码只显示数据库中的一行. 我的守则 import java.io.FileNotFo ...

最新文章

  1. VC++ 打开文件夹,保存文件等对话框的调用
  2. oracle创建数据库总结,oracle创建数据库和用户方法总结
  3. golang ping go-ping库 简介
  4. 小程序如何用data的数据控制页面展示_17. 教你零基础搭建小程序:小程序事件绑定(1)
  5. ABAP Netweaver和Hybris Enterprise Commerce Platform的登录认证
  6. 分布式经典书籍--深入分布式缓存 从原理到实践
  7. 字符串对象的各种方法
  8. 一个基于WF的业务流程平台
  9. princomp 与pca的区别与联系
  10. vue 状态管理vuex(九)
  11. 2022恒生电子前端笔试
  12. layui 表格前端分页
  13. Matlab中Fatal Error On Startup
  14. LeetCode311 稀疏矩阵的乘法
  15. Zoned-Storage - 对ZNS块设备进行基准测试
  16. 大数据工具千千万,到底谁才是最强王者?
  17. 计算机word文档无法工作,win10所有word文档都打不开如何解决_win10电脑所有word文档无法打开解决教程...
  18. 线程的故事(了解线程生命周期)
  19. 已知信码序列为1011_某一个数据通信系统采用CRC校验方式,其中:生成多项式G(X)=...
  20. docker安装kong和konga详细说明

热门文章

  1. 为什么Netty这么火?与Mina相比有什么优势?
  2. Oracle入门(十一)之SQL
  3. “小朋友”们节日快乐呀~
  4. logback-spring.xml配置文件
  5. 尚硅谷2020最新版SpringCloud(H版alibaba)框架开发教程全套完整版从入门到精通
  6. 如何安装mysql5.5.6_centos6安装mysql5.5.53
  7. servlet session持久化
  8. mysql事务基础+基于innodb的行锁+间隙锁+如何锁定行
  9. mega x_[MEGA DEAL] 2020年完整的Java Master Class Bundle(96%)
  10. php cdi_Quarkus的其他(非标准)CDI功能