新增LDAP认证登录
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.common.shiro.authc;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* LdapToken
|
||||
* @author ThinkGem
|
||||
* @version 2021-7-6
|
||||
*/
|
||||
public class LdapToken extends FormToken {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public LdapToken() {
|
||||
super();
|
||||
}
|
||||
|
||||
public LdapToken(String username, char[] password, boolean rememberMe,
|
||||
String host, Map<String, Object> params) {
|
||||
super(username, password, rememberMe, null, host, params);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.common.shiro.filter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
|
||||
import com.jeesite.common.shiro.authc.LdapToken;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
|
||||
/**
|
||||
* LDAP过滤器
|
||||
* @author ThinkGem
|
||||
* @version 2021-7-6
|
||||
*/
|
||||
public class LdapFilter extends FormFilter {
|
||||
|
||||
@Override
|
||||
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
|
||||
String username = getUsername(request, response); // 用户名
|
||||
String password = getPassword(request); // 登录密码
|
||||
boolean rememberMe = isRememberMe(request); // 记住我(自动登录)
|
||||
String host = getHost(request); // 登录主机
|
||||
Map<String, Object> paramMap = ServletUtils.getExtParams(request); // 登录附加参数
|
||||
return new LdapToken(username, password.toCharArray(), rememberMe, host, paramMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isLoginRequest(ServletRequest request, ServletResponse response) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.common.shiro.realm;
|
||||
|
||||
import javax.naming.AuthenticationNotSupportedException;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.ldap.LdapContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
import org.apache.shiro.ldap.UnsupportedAuthenticationMechanismException;
|
||||
import org.apache.shiro.realm.ldap.DefaultLdapRealm;
|
||||
import org.apache.shiro.realm.ldap.JndiLdapContextFactory;
|
||||
import org.apache.shiro.realm.ldap.LdapContextFactory;
|
||||
import org.apache.shiro.realm.ldap.LdapUtils;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.util.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jeesite.common.shiro.authc.FormToken;
|
||||
import com.jeesite.common.shiro.authc.LdapToken;
|
||||
import com.jeesite.common.utils.SpringUtils;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
import com.jeesite.modules.sys.entity.User;
|
||||
import com.jeesite.modules.sys.service.EmpUserService;
|
||||
import com.jeesite.modules.sys.service.UserService;
|
||||
import com.jeesite.modules.sys.utils.LogUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
|
||||
/**
|
||||
* 系统认证授权实现类
|
||||
* @author ThinkGem
|
||||
* @version 2021-7-6
|
||||
*/
|
||||
public class LdapAuthorizingRealm extends BaseAuthorizingRealm {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DefaultLdapRealm.class);
|
||||
|
||||
//The zero index currently means nothing, but could be utilized in the future for other substitution techniques.
|
||||
private static final String USERDN_SUBSTITUTION_TOKEN = "{0}";
|
||||
|
||||
private String userDnPrefix;
|
||||
private String userDnSuffix;
|
||||
|
||||
/**
|
||||
* The LdapContextFactory instance used to acquire {@link javax.naming.ldap.LdapContext LdapContext}'s at runtime
|
||||
* to acquire connections to the LDAP directory to perform authentication attempts and authorizatino queries.
|
||||
*/
|
||||
private LdapContextFactory contextFactory;
|
||||
|
||||
private UserService userService;
|
||||
private EmpUserService empUserService;
|
||||
|
||||
/**
|
||||
* Default no-argument constructor that defaults the internal {@link LdapContextFactory} instance to a
|
||||
* {@link JndiLdapContextFactory}.
|
||||
*/
|
||||
public LdapAuthorizingRealm() {
|
||||
super();
|
||||
//Credentials Matching is not necessary - the LDAP directory will do it automatically:
|
||||
setCredentialsMatcher(new AllowAllCredentialsMatcher());
|
||||
//Any Object principal and Object credentials may be passed to the LDAP provider, so accept any token:
|
||||
setAuthenticationTokenClass(LdapToken.class);
|
||||
this.contextFactory = new JndiLdapContextFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FormToken getFormToken(AuthenticationToken authcToken) {
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
if (authcToken == null){
|
||||
return null;
|
||||
}
|
||||
LdapToken ldapToken = (LdapToken) authcToken;
|
||||
|
||||
// LDAP 身份认证
|
||||
LdapContext ctx = null;
|
||||
try {
|
||||
Object principal = getUserDn(ldapToken.getUsername());
|
||||
Object credentials = String.valueOf(ldapToken.getPassword());
|
||||
log.debug("Authenticating user '{}' through LDAP", principal);
|
||||
ctx = getContextFactory().getLdapContext(principal, credentials);
|
||||
} catch (AuthenticationNotSupportedException e) {
|
||||
throw new UnsupportedAuthenticationMechanismException("msg:LDAP 不支持的授权类型", e);
|
||||
} catch (javax.naming.AuthenticationException e) {
|
||||
throw new AuthenticationException("msg:LDAP 授权失败:"+e.getMessage(), e);
|
||||
} catch (NamingException e) {
|
||||
throw new AuthenticationException("msg:LDAP 连接失败:"+e.getMessage(), e);
|
||||
} catch (Exception e) {
|
||||
throw new AuthenticationException("msg:LDAP 登录失败:"+e.getMessage(), e);
|
||||
} finally {
|
||||
LdapUtils.closeContext(ctx);
|
||||
}
|
||||
|
||||
// 生成登录信息对象
|
||||
FormToken token = new FormToken(request);
|
||||
token.setUsername(ldapToken.getUsername());
|
||||
token.setPassword(ldapToken.getPassword());
|
||||
token.setParams(ldapToken.getParams());
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected User getUserInfo(FormToken token) {
|
||||
User user = super.getUserInfo(token);
|
||||
if (user == null){
|
||||
throw new AuthenticationException("msg:用户 “" + token.getUsername() + "” 在本系统中不存在, 请联系管理员.");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertCredentialsMatch(AuthenticationToken authcToken,
|
||||
AuthenticationInfo info) throws AuthenticationException {
|
||||
// 已经在 getFormToken 认证过了,这里就不验证身份了
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(LoginInfo loginInfo, Subject subject, Session session, User user) {
|
||||
return super.doGetAuthorizationInfo(loginInfo, subject, session, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoginSuccess(LoginInfo loginInfo, HttpServletRequest request) {
|
||||
super.onLoginSuccess(loginInfo, request);
|
||||
|
||||
//System.out.print("__sid: "+request.getSession().getId());
|
||||
//System.out.println(" == "+UserUtils.getSession().getId());
|
||||
|
||||
// 更新登录IP、时间、会话ID等
|
||||
User user = UserUtils.get(loginInfo.getId());
|
||||
getUserService().updateUserLoginInfo(user);
|
||||
|
||||
// 记录用户登录日志
|
||||
LogUtils.saveLog(user, ServletUtils.getRequest(), "系统登录", Log.TYPE_LOGIN_LOGOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(LoginInfo loginInfo, HttpServletRequest request) {
|
||||
super.onLogoutSuccess(loginInfo, request);
|
||||
|
||||
// 记录用户退出日志
|
||||
User user = UserUtils.get(loginInfo.getId());
|
||||
LogUtils.saveLog(user, request, "系统退出", Log.TYPE_LOGIN_LOGOUT);
|
||||
}
|
||||
|
||||
public UserService getUserService() {
|
||||
if (userService == null){
|
||||
userService = SpringUtils.getBean(UserService.class);
|
||||
}
|
||||
return userService;
|
||||
}
|
||||
|
||||
public EmpUserService getEmpUserService() {
|
||||
if (empUserService == null){
|
||||
empUserService = SpringUtils.getBean(EmpUserService.class);
|
||||
}
|
||||
return empUserService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the User DN prefix to use when building a runtime User DN value or {@code null} if no
|
||||
* {@link #getUserDnTemplate() userDnTemplate} has been configured. If configured, this value is the text that
|
||||
* occurs before the {@link #USERDN_SUBSTITUTION_TOKEN} in the {@link #getUserDnTemplate() userDnTemplate} value.
|
||||
*
|
||||
* @return the the User DN prefix to use when building a runtime User DN value or {@code null} if no
|
||||
* {@link #getUserDnTemplate() userDnTemplate} has been configured.
|
||||
*/
|
||||
protected String getUserDnPrefix() {
|
||||
return userDnPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the User DN suffix to use when building a runtime User DN value. or {@code null} if no
|
||||
* {@link #getUserDnTemplate() userDnTemplate} has been configured. If configured, this value is the text that
|
||||
* occurs after the {@link #USERDN_SUBSTITUTION_TOKEN} in the {@link #getUserDnTemplate() userDnTemplate} value.
|
||||
*
|
||||
* @return the User DN suffix to use when building a runtime User DN value or {@code null} if no
|
||||
* {@link #getUserDnTemplate() userDnTemplate} has been configured.
|
||||
*/
|
||||
protected String getUserDnSuffix() {
|
||||
return userDnSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the User Distinguished Name (DN) template to use when creating User DNs at runtime. A User DN is an LDAP
|
||||
* fully-qualified unique user identifier which is required to establish a connection with the LDAP
|
||||
* directory to authenticate users and query for authorization information.
|
||||
* <h2>Usage</h2>
|
||||
* User DN formats are unique to the LDAP directory's schema, and each environment differs - you will need to
|
||||
* specify the format corresponding to your directory. You do this by specifying the full User DN as normal, but
|
||||
* but you use a <b>{@code {0}}</b> placeholder token in the string representing the location where the
|
||||
* user's submitted principal (usually a username or uid) will be substituted at runtime.
|
||||
* <p/>
|
||||
* For example, if your directory
|
||||
* uses an LDAP {@code uid} attribute to represent usernames, the User DN for the {@code jsmith} user may look like
|
||||
* this:
|
||||
* <p/>
|
||||
* <pre>uid=jsmith,ou=users,dc=mycompany,dc=com</pre>
|
||||
* <p/>
|
||||
* in which case you would set this property with the following template value:
|
||||
* <p/>
|
||||
* <pre>uid=<b>{0}</b>,ou=users,dc=mycompany,dc=com</pre>
|
||||
* <p/>
|
||||
* If no template is configured, the raw {@code AuthenticationToken}
|
||||
* {@link AuthenticationToken#getPrincipal() principal} will be used as the LDAP principal. This is likely
|
||||
* incorrect as most LDAP directories expect a fully-qualified User DN as opposed to the raw uid or username. So,
|
||||
* ensure you set this property to match your environment!
|
||||
*
|
||||
* @param template the User Distinguished Name template to use for runtime substitution
|
||||
* @throws IllegalArgumentException if the template is null, empty, or does not contain the
|
||||
* {@code {0}} substitution token.
|
||||
* @see LdapContextFactory#getLdapContext(Object,Object)
|
||||
*/
|
||||
public void setUserDnTemplate(String template) throws IllegalArgumentException {
|
||||
if (!StringUtils.hasText(template)) {
|
||||
return;
|
||||
}
|
||||
int index = template.indexOf(USERDN_SUBSTITUTION_TOKEN);
|
||||
if (index < 0) {
|
||||
String msg = "User DN template must contain the '" +
|
||||
USERDN_SUBSTITUTION_TOKEN + "' replacement token to understand where to " +
|
||||
"insert the runtime authentication principal.";
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
String prefix = template.substring(0, index);
|
||||
String suffix = template.substring(prefix.length() + USERDN_SUBSTITUTION_TOKEN.length());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Determined user DN prefix [{}] and suffix [{}]", prefix, suffix);
|
||||
}
|
||||
this.userDnPrefix = prefix;
|
||||
this.userDnSuffix = suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the User Distinguished Name (DN) template to use when creating User DNs at runtime - see the
|
||||
* {@link #setUserDnTemplate(String) setUserDnTemplate} JavaDoc for a full explanation.
|
||||
*
|
||||
* @return the User Distinguished Name (DN) template to use when creating User DNs at runtime.
|
||||
*/
|
||||
public String getUserDnTemplate() {
|
||||
return getUserDn(USERDN_SUBSTITUTION_TOKEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the LDAP User Distinguished Name (DN) to use when acquiring an
|
||||
* {@link javax.naming.ldap.LdapContext LdapContext} from the {@link LdapContextFactory}.
|
||||
* <p/>
|
||||
* If the the {@link #getUserDnTemplate() userDnTemplate} property has been set, this implementation will construct
|
||||
* the User DN by substituting the specified {@code principal} into the configured template. If the
|
||||
* {@link #getUserDnTemplate() userDnTemplate} has not been set, the method argument will be returned directly
|
||||
* (indicating that the submitted authentication token principal <em>is</em> the User DN).
|
||||
*
|
||||
* @param principal the principal to substitute into the configured {@link #getUserDnTemplate() userDnTemplate}.
|
||||
* @return the constructed User DN to use at runtime when acquiring an {@link javax.naming.ldap.LdapContext}.
|
||||
* @throws IllegalArgumentException if the method argument is null or empty
|
||||
* @throws IllegalStateException if the {@link #getUserDnTemplate userDnTemplate} has not been set.
|
||||
* @see LdapContextFactory#getLdapContext(Object, Object)
|
||||
*/
|
||||
protected String getUserDn(String principal) throws IllegalArgumentException, IllegalStateException {
|
||||
if (!StringUtils.hasText(principal)) {
|
||||
throw new IllegalArgumentException("User principal cannot be null or empty for User DN construction.");
|
||||
}
|
||||
String prefix = getUserDnPrefix();
|
||||
String suffix = getUserDnSuffix();
|
||||
if (prefix == null && suffix == null) {
|
||||
log.debug("userDnTemplate property has not been configured, indicating the submitted " +
|
||||
"AuthenticationToken's principal is the same as the User DN. Returning the method argument " +
|
||||
"as is.");
|
||||
return principal;
|
||||
}
|
||||
|
||||
int prefixLength = prefix != null ? prefix.length() : 0;
|
||||
int suffixLength = suffix != null ? suffix.length() : 0;
|
||||
StringBuilder sb = new StringBuilder(prefixLength + principal.length() + suffixLength);
|
||||
if (prefixLength > 0) {
|
||||
sb.append(prefix);
|
||||
}
|
||||
sb.append(principal);
|
||||
if (suffixLength > 0) {
|
||||
sb.append(suffix);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LdapContextFactory instance used to acquire connections to the LDAP directory during authentication
|
||||
* attempts and authorization queries. Unless specified otherwise, the default is a {@link JndiLdapContextFactory}
|
||||
* instance.
|
||||
*
|
||||
* @param contextFactory the LdapContextFactory instance used to acquire connections to the LDAP directory during
|
||||
* authentication attempts and authorization queries
|
||||
*/
|
||||
public void setContextFactory(LdapContextFactory contextFactory) {
|
||||
this.contextFactory = contextFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the LdapContextFactory instance used to acquire connections to the LDAP directory during authentication
|
||||
* attempts and authorization queries. Unless specified otherwise, the default is a {@link JndiLdapContextFactory}
|
||||
* instance.
|
||||
*
|
||||
* @return the LdapContextFactory instance used to acquire connections to the LDAP directory during
|
||||
* authentication attempts and authorization queries
|
||||
*/
|
||||
public LdapContextFactory getContextFactory() {
|
||||
return this.contextFactory;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import javax.servlet.Filter;
|
||||
import org.apache.shiro.cache.CacheManager;
|
||||
import org.apache.shiro.cas.CasSubjectFactory;
|
||||
import org.apache.shiro.realm.Realm;
|
||||
import org.apache.shiro.realm.ldap.JndiLdapContextFactory;
|
||||
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.web.filter.InvalidRequestFilter;
|
||||
@@ -29,12 +30,14 @@ import com.jeesite.common.shiro.config.FilterChainDefinitionMap;
|
||||
import com.jeesite.common.shiro.filter.CasFilter;
|
||||
import com.jeesite.common.shiro.filter.FormFilter;
|
||||
import com.jeesite.common.shiro.filter.InnerFilter;
|
||||
import com.jeesite.common.shiro.filter.LdapFilter;
|
||||
import com.jeesite.common.shiro.filter.LogoutFilter;
|
||||
import com.jeesite.common.shiro.filter.PermissionsFilter;
|
||||
import com.jeesite.common.shiro.filter.RolesFilter;
|
||||
import com.jeesite.common.shiro.filter.UserFilter;
|
||||
import com.jeesite.common.shiro.realm.AuthorizingRealm;
|
||||
import com.jeesite.common.shiro.realm.CasAuthorizingRealm;
|
||||
import com.jeesite.common.shiro.realm.LdapAuthorizingRealm;
|
||||
import com.jeesite.common.shiro.session.SessionDAO;
|
||||
import com.jeesite.common.shiro.session.SessionManager;
|
||||
import com.jeesite.common.shiro.web.ShiroFilterFactoryBean;
|
||||
@@ -77,6 +80,15 @@ public class ShiroConfig {
|
||||
bean.setAuthorizingRealm(casAuthorizingRealm);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP登录过滤器
|
||||
*/
|
||||
private LdapFilter shiroLdapFilter(LdapAuthorizingRealm ldapAuthorizingRealm) {
|
||||
LdapFilter bean = new LdapFilter();
|
||||
bean.setAuthorizingRealm(ldapAuthorizingRealm);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form登录过滤器
|
||||
@@ -131,7 +143,7 @@ public class ShiroConfig {
|
||||
*/
|
||||
@Bean
|
||||
public ShiroFilterFactoryBean shiroFilter(WebSecurityManager webSecurityManager, AuthorizingRealm authorizingRealm,
|
||||
CasAuthorizingRealm casAuthorizingRealm) {
|
||||
CasAuthorizingRealm casAuthorizingRealm, LdapAuthorizingRealm ldapAuthorizingRealm) {
|
||||
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
|
||||
bean.setSecurityManager(webSecurityManager);
|
||||
bean.setLoginUrl(Global.getProperty("shiro.loginUrl"));
|
||||
@@ -139,6 +151,7 @@ public class ShiroConfig {
|
||||
Map<String, Filter> filters = bean.getFilters();
|
||||
filters.put("inner", shiroInnerFilter());
|
||||
filters.put("cas", shiroCasFilter(casAuthorizingRealm));
|
||||
filters.put("ldap", shiroLdapFilter(ldapAuthorizingRealm));
|
||||
filters.put("authc", shiroAuthcFilter(authorizingRealm));
|
||||
filters.put("logout", shiroLogoutFilter(authorizingRealm));
|
||||
filters.put("perms", shiroPermsFilter());
|
||||
@@ -182,17 +195,31 @@ public class ShiroConfig {
|
||||
bean.setCasServerCallbackUrl(Global.getProperty("shiro.casClientUrl") + Global.getAdminPath() + "/login-cas");
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP安全认证实现类
|
||||
*/
|
||||
@Bean
|
||||
public LdapAuthorizingRealm ldapAuthorizingRealm(SessionDAO sessionDAO, CasOutHandler casOutHandler) {
|
||||
LdapAuthorizingRealm bean = new LdapAuthorizingRealm();
|
||||
JndiLdapContextFactory contextFactory = (JndiLdapContextFactory) bean.getContextFactory();
|
||||
contextFactory.setUrl(Global.getProperty("shiro.ldapUrl"/*, "ldap://127.0.0.1:389"*/));
|
||||
bean.setUserDnTemplate(Global.getProperty("shiro.ldapUserDn"/*, "uid={0},ou=users,dc=mycompany,dc=com"*/));
|
||||
bean.setSessionDAO(sessionDAO);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义Shiro安全管理配置
|
||||
*/
|
||||
@Bean
|
||||
public WebSecurityManager webSecurityManager(AuthorizingRealm authorizingRealm, CasAuthorizingRealm casAuthorizingRealm,
|
||||
SessionManager sessionManager, CacheManager shiroCacheManager) {
|
||||
LdapAuthorizingRealm ldapAuthorizingRealm, SessionManager sessionManager, CacheManager shiroCacheManager) {
|
||||
WebSecurityManager bean = new WebSecurityManager();
|
||||
Collection<Realm> realms = ListUtils.newArrayList();
|
||||
realms.add(authorizingRealm); // 第一个为权限授权控制类
|
||||
realms.add(casAuthorizingRealm);
|
||||
realms.add(ldapAuthorizingRealm);
|
||||
bean.setRealms(realms);
|
||||
bean.setSessionManager(sessionManager);
|
||||
bean.setCacheManager(shiroCacheManager);
|
||||
|
||||
@@ -332,6 +332,10 @@ shiro:
|
||||
# logoutUrl: ${shiro.casServerUrl}/logout?service=${shiro.loginUrl}
|
||||
# successUrl: ${shiro.casClientUrl}${adminPath}/index
|
||||
|
||||
# # LDAP 相关设置(标准版)
|
||||
# ldapUrl: ldap://127.0.0.1:389
|
||||
# ldapUserDn: uid={0},ou=users,dc=mycompany,dc=com
|
||||
|
||||
# 简单 SSO 登录相关配置
|
||||
sso:
|
||||
# 如果启用/sso/{username}/{token}单点登录,请修改此安全key并与单点登录系统key一致。
|
||||
@@ -423,6 +427,7 @@ shiro:
|
||||
/druid/** = perms[sys:state:druid]
|
||||
/bpm/modeler/** = perms[bpm:modeler]
|
||||
${adminPath}/login-cas = cas
|
||||
${adminPath}/login-ldap = ldap
|
||||
${adminPath}/login = authc
|
||||
${adminPath}/logout = logout
|
||||
${adminPath}/file/** = user
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
<ul id="loginTab" class="nav nav-tabs">
|
||||
<li class="active"><a href="#tab-1" data-toggle="tab" action="${ctx}/login">${text('账号登录')}</a></li>
|
||||
<li><a href="#tab-2" data-toggle="tab" action="${ctxPath}/account/loginByValidCode">${text('手机登录')}</a></li>
|
||||
<% if(isNotBlank(@Global.getConfig('shiro.ldapUrl'))){ %>
|
||||
<li><a href="#tab-3" data-toggle="tab" action="${ctx}/login-ldap">${text('LDAP登录')}</a></li>
|
||||
<% } %>
|
||||
</ul>
|
||||
<% } %>
|
||||
<#form:form id="loginForm" model="${user!}" action="${ctx}/login" method="post" class="tab-content">
|
||||
@@ -28,7 +31,7 @@
|
||||
data-msg-required="${text('请填写登录账号.')}" placeholder="${text('登录账号')}"
|
||||
value="${cookie('rememberUserCode')}"/>
|
||||
</div>
|
||||
<div class="form-group has-feedback tab-pane tab-1 active">
|
||||
<div class="form-group has-feedback tab-pane tab-1 tab-3 active">
|
||||
<span class="icon-lock form-control-feedback" title="${text('登录密码,鼠标按下显示密码')}"
|
||||
onmousedown="$('#password').attr('type','text')" onmouseup="$('#password').attr('type','password')"
|
||||
onmouseenter="$(this).removeClass('icon-lock').addClass('icon-eye')"
|
||||
|
||||
Reference in New Issue
Block a user