单点登录接口和无条件登录接口优化改进,并在调用登录时统一增加登录成功和失败事件,方便返回登录信息。
This commit is contained in:
@@ -3,44 +3,34 @@
|
||||
*/
|
||||
package com.jeesite.common.shiro.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.shiro.realm.CasAuthorizingRealm;
|
||||
import com.jeesite.common.shiro.realm.LoginInfo;
|
||||
|
||||
/**
|
||||
* CAS过滤器
|
||||
* @author ThinkGem
|
||||
* @version 2018-7-11
|
||||
* @version 2020-9-19
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter {
|
||||
|
||||
private CasAuthorizingRealm authorizingRealm; // 安全认证类
|
||||
|
||||
/**
|
||||
* 登录成功调用事件
|
||||
*/
|
||||
@Override
|
||||
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
|
||||
|
||||
// 登录成功后初始化授权信息并处理登录后的操作
|
||||
authorizingRealm.onLoginSuccess((LoginInfo)subject.getPrincipal(), (HttpServletRequest)request);
|
||||
|
||||
// AJAX不支持Redirect改用Forward
|
||||
request.getRequestDispatcher(getSuccessUrl()).forward(request, response);
|
||||
return false;
|
||||
return FormAuthenticationFilter.onLoginSuccess((HttpServletRequest)request, (HttpServletResponse)response);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,15 +49,15 @@ public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter {
|
||||
return false;
|
||||
} else {
|
||||
try {
|
||||
if (ae != null && StringUtils.startsWith(ae.getMessage(), "msg:")){
|
||||
String message = ExceptionUtils.getExceptionMessage(ae);
|
||||
if (StringUtils.isNotBlank(message)){
|
||||
request.setAttribute("exception", ae);
|
||||
request.setAttribute("message", message);
|
||||
request.getRequestDispatcher("/error/403").forward(request, response);
|
||||
}else{
|
||||
WebUtils.issueRedirect(request, response, getLoginUrl());
|
||||
}
|
||||
} catch (ServletException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
@@ -75,7 +65,7 @@ public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter {
|
||||
}
|
||||
|
||||
public void setAuthorizingRealm(CasAuthorizingRealm authorizingRealm) {
|
||||
this.authorizingRealm = authorizingRealm;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.network.IpUtils;
|
||||
import com.jeesite.common.shiro.authc.FormToken;
|
||||
import com.jeesite.common.shiro.realm.BaseAuthorizingRealm;
|
||||
import com.jeesite.common.shiro.realm.LoginInfo;
|
||||
import com.jeesite.common.web.CookieUtils;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
@@ -45,20 +44,20 @@ import com.jeesite.modules.sys.utils.UserUtils;
|
||||
/**
|
||||
* 表单验证(包含验证码)过滤类
|
||||
* @author ThinkGem
|
||||
* @version 2020-4-13
|
||||
* @version 2020-9-19
|
||||
*/
|
||||
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {
|
||||
|
||||
public static final String CAPTCHA_PARAM = "validCode"; // 验证码
|
||||
public static final String MESSAGE_PARAM = "message"; // 登录返回消息
|
||||
public static final String REMEMBER_USERCODE_PARAM = "rememberUserCode"; // 记住用户名
|
||||
public static final String EXCEPTION_ATTRIBUTE_NAME = "exception"; // 异常类属性名
|
||||
public static final String CAPTCHA_PARAM = "validCode"; // 验证码
|
||||
public static final String MESSAGE_PARAM = "message"; // 登录返回消息
|
||||
public static final String REMEMBER_USERCODE_PARAM = "rememberUserCode"; // 记住用户名
|
||||
public static final String EXCEPTION_ATTRIBUTE_NAME = "exception"; // 异常类属性名
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FormAuthenticationFilter.class);
|
||||
|
||||
private BaseAuthorizingRealm authorizingRealm; // 安全认证类
|
||||
private static FormAuthenticationFilter instance;
|
||||
|
||||
private Cookie rememberUserCodeCookie; // 记住用户名Cookie
|
||||
private BaseAuthorizingRealm authorizingRealm;
|
||||
private Cookie rememberUserCodeCookie; // 记住用户名Cookie
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
@@ -68,8 +67,16 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
rememberUserCodeCookie = new SimpleCookie(REMEMBER_USERCODE_PARAM);
|
||||
rememberUserCodeCookie.setHttpOnly(true);
|
||||
rememberUserCodeCookie.setMaxAge(Cookie.ONE_YEAR);
|
||||
instance = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建登录授权令牌
|
||||
*/
|
||||
public static FormToken newToken(HttpServletRequest request, HttpServletResponse response) {
|
||||
return (FormToken)instance.createToken(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建登录授权令牌
|
||||
*/
|
||||
@@ -100,7 +107,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
logger.info("登录账号为空或解码错误.");
|
||||
}
|
||||
}
|
||||
// 登录成功后,判断是否需要记住用户名
|
||||
// 登录时判断是否需要记住用户名
|
||||
if (WebUtils.isTrue(request, REMEMBER_USERCODE_PARAM)) {
|
||||
rememberUserCodeCookie.setValue(EncodeUtils.encodeUrl(EncodeUtils.xssFilter(username)));
|
||||
rememberUserCodeCookie.saveTo((HttpServletRequest)request, (HttpServletResponse)response);
|
||||
@@ -241,30 +248,51 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
return super.executeLogin(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功调用事件(静态方便其他位置调用)
|
||||
*/
|
||||
public static boolean onLoginSuccess(HttpServletRequest request, HttpServletResponse response) {
|
||||
try {
|
||||
return instance.onLoginSuccess(null, null, request, response);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功调用事件
|
||||
*/
|
||||
@Override
|
||||
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
|
||||
|
||||
// 登录成功后初始化授权信息并处理登录后的操作
|
||||
authorizingRealm.onLoginSuccess((LoginInfo)subject.getPrincipal(), (HttpServletRequest) request);
|
||||
|
||||
authorizingRealm.onLoginSuccess(UserUtils.getLoginInfo(), (HttpServletRequest)request);
|
||||
// AJAX不支持Redirect改用Forward
|
||||
request.getRequestDispatcher(getSuccessUrl()).forward(request, response);
|
||||
try {
|
||||
request.getRequestDispatcher(getSuccessUrl()).forward(request, response);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录失败调用事件(静态方便其他位置调用)
|
||||
*/
|
||||
public static boolean onLoginFailure(AuthenticationException e, HttpServletRequest request, HttpServletResponse response) {
|
||||
return instance.onLoginFailure(null, e, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录失败调用事件
|
||||
*/
|
||||
@Override
|
||||
protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
|
||||
String message = StringUtils.EMPTY;
|
||||
if (e instanceof IncorrectCredentialsException || e instanceof UnknownAccountException) {
|
||||
message = Global.getText("sys.login.failure");
|
||||
} else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")) {
|
||||
if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")) {
|
||||
message = StringUtils.replace(e.getMessage(), "msg:", "");
|
||||
} else if (e instanceof IncorrectCredentialsException || e instanceof UnknownAccountException) {
|
||||
message = Global.getText("sys.login.failure");
|
||||
} else {
|
||||
message = Global.getText("sys.login.error");
|
||||
logger.error(message, e); // 输出到日志文件
|
||||
@@ -272,20 +300,20 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
request.setAttribute(EXCEPTION_ATTRIBUTE_NAME, e);
|
||||
request.setAttribute(MESSAGE_PARAM, message);
|
||||
|
||||
// 登录操作如果是Ajax操作,直接返回登录信息字符串。
|
||||
if (ServletUtils.isAjaxRequest(((HttpServletRequest) request))){
|
||||
Map<String, Object> data = getLoginFailureData(((HttpServletRequest) request), ((HttpServletResponse) response));
|
||||
ServletUtils.renderResult(((HttpServletResponse) response), Global.TRUE, message, data);
|
||||
return false;
|
||||
// AJAX不支持Redirect改用Forward
|
||||
try {
|
||||
String loginFailureUrl = Global.getProperty("adminPath")+"/loginFailure";
|
||||
request.getRequestDispatcher(loginFailureUrl).forward(request, response);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setAuthorizingRealm(BaseAuthorizingRealm authorizingRealm) {
|
||||
this.authorizingRealm = authorizingRealm;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录页面数据
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static Map<String, Object> getLoginData(HttpServletRequest request, HttpServletResponse response) {
|
||||
Map<String, Object> data = MapUtils.newHashMap();
|
||||
|
||||
@@ -294,7 +322,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
for (Entry<String, Object> entry : paramMap.entrySet()){
|
||||
data.put(ServletUtils.EXT_PARAMS_PREFIX + entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
|
||||
// 如果已登录,再次访问主页,则退出原账号。
|
||||
if (!Global.TRUE.equals(Global.getConfig("shiro.isAllowRefreshIndex"))){
|
||||
CookieUtils.setCookie(response, "LOGINED", "false");
|
||||
@@ -316,6 +344,10 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录失败数据
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static Map<String, Object> getLoginFailureData(HttpServletRequest request, HttpServletResponse response) {
|
||||
Map<String, Object> data = MapUtils.newHashMap();
|
||||
|
||||
@@ -362,4 +394,9 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
data.put("result", Global.FALSE);
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setAuthorizingRealm(BaseAuthorizingRealm authorizingRealm) {
|
||||
this.authorizingRealm = authorizingRealm;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,7 +38,7 @@ import com.jeesite.modules.sys.utils.UserUtils;
|
||||
/**
|
||||
* 系统安全认证实现类
|
||||
* @author ThinkGem
|
||||
* @version 2018-7-11
|
||||
* @version 2020-9-19
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class CasAuthorizingRealm extends BaseAuthorizingRealm {
|
||||
@@ -92,7 +92,7 @@ public class CasAuthorizingRealm extends BaseAuthorizingRealm {
|
||||
casToken.setUserId(casPrincipal.getName());
|
||||
|
||||
// 生成登录信息对象
|
||||
FormToken token = new FormToken();
|
||||
FormToken token = new FormToken(request);
|
||||
token.setUsername(casPrincipal.getName());
|
||||
Map<String, Object> params = MapUtils.newHashMap();
|
||||
params.putAll(casPrincipal.getAttributes());
|
||||
|
||||
@@ -37,14 +37,14 @@ import com.jeesite.modules.sys.utils.UserUtils;
|
||||
/**
|
||||
* 登录Controller
|
||||
* @author ThinkGem
|
||||
* @version 2020-4-13
|
||||
* @version 2020-9-19
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "${adminPath}")
|
||||
public class LoginController extends BaseController{
|
||||
|
||||
/**
|
||||
* 管理登录
|
||||
* 登录页面
|
||||
*/
|
||||
@RequestMapping(value = "login", method = RequestMethod.GET)
|
||||
public String login(HttpServletRequest request, HttpServletResponse response, Model model) {
|
||||
@@ -94,9 +94,9 @@ public class LoginController extends BaseController{
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录失败,真正登录的POST请求由Filter完成
|
||||
* 登录失败,返回错误信息
|
||||
*/
|
||||
@RequestMapping(value = "login", method = RequestMethod.POST)
|
||||
@RequestMapping(value = "loginFailure")
|
||||
public String loginFailure(HttpServletRequest request, HttpServletResponse response, Model model) {
|
||||
LoginInfo loginInfo = UserUtils.getLoginInfo();
|
||||
|
||||
@@ -200,6 +200,9 @@ public class LoginController extends BaseController{
|
||||
|
||||
// 获取登录成功后跳转的页面
|
||||
String successUrl = request.getParameter("__url");
|
||||
if (StringUtils.isBlank(successUrl)){
|
||||
successUrl = (String)request.getAttribute("__url");
|
||||
}
|
||||
if (StringUtils.isBlank(successUrl)){
|
||||
successUrl = Global.getProperty("shiro.successUrl");
|
||||
}
|
||||
@@ -272,16 +275,16 @@ public class LoginController extends BaseController{
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取侧边栏菜单数据
|
||||
* 侧边栏菜单数据
|
||||
*/
|
||||
@RequiresPermissions("user")
|
||||
@RequestMapping(value = "index/menuTree")
|
||||
public String indexMenuTree(String parentCode) {
|
||||
return "modules/sys/sysIndex/menuTree";
|
||||
return "modules/sys/menuTree";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户权限字符串数据(移动端用)
|
||||
* 当前用户权限字符串数据(移动端用)
|
||||
*/
|
||||
@RequiresPermissions("user")
|
||||
@RequestMapping(value = "authInfo")
|
||||
@@ -291,7 +294,7 @@ public class LoginController extends BaseController{
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户菜单数据(移动端用)
|
||||
* 当前用户菜单数据(移动端用)
|
||||
*/
|
||||
@RequiresPermissions("user")
|
||||
@RequestMapping(value = "menuTree")
|
||||
@@ -334,7 +337,7 @@ public class LoginController extends BaseController{
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换主题
|
||||
* 切换主题风格
|
||||
*/
|
||||
@RequiresPermissions("user")
|
||||
@RequestMapping(value = "switchSkin/{skinName}")
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.shiro.authc.FormToken;
|
||||
import com.jeesite.common.shiro.filter.FormAuthenticationFilter;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.modules.sys.entity.User;
|
||||
@@ -26,7 +27,7 @@ import com.jeesite.modules.sys.utils.UserUtils;
|
||||
/**
|
||||
* 单点登录Controller
|
||||
* @author ThinkGem
|
||||
* @version 2017-03-25
|
||||
* @version 2020-9-19
|
||||
*/
|
||||
@Controller
|
||||
public class SsoController extends BaseController{
|
||||
@@ -63,24 +64,20 @@ public class SsoController extends BaseController{
|
||||
// 通过令牌登录系统
|
||||
if (token != null){
|
||||
try {
|
||||
FormToken upToken = new FormToken();
|
||||
upToken.setUsername(username); // 登录用户名
|
||||
upToken.setSsoToken(token); // 单点登录令牌
|
||||
upToken.setParams(ServletUtils.getExtParams(request)); // 登录附加参数
|
||||
UserUtils.getSubject().login(upToken);
|
||||
if (ServletUtils.isAjaxRequest(request)){
|
||||
return ServletUtils.renderResult(response, Global.TRUE, text("账号登录成功"));
|
||||
}else{
|
||||
return REDIRECT + EncodeUtils.decodeUrl2(url);
|
||||
}
|
||||
// FormToken 构造方法的三个参数:登录名、单点登录的令牌秘钥、请求对象
|
||||
UserUtils.getSubject().login(new FormToken(username, token, request));
|
||||
request.setAttribute("__url", EncodeUtils.decodeUrl2(url));
|
||||
FormAuthenticationFilter.onLoginSuccess(request, response);
|
||||
} catch (AuthenticationException e) {
|
||||
if (!e.getMessage().startsWith("msg:")){
|
||||
throw new AuthenticationException("msg:登录失败,请联系管理员。", e);
|
||||
}
|
||||
throw e;
|
||||
FormAuthenticationFilter.onLoginFailure(e, request, response);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return "error/403";
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// System.out.println(UserUtils.getSsoToken("system"));
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user