您的位置:首页 > 其它

关于登陆的配置问题总结

2017-06-17 14:23 381 查看
spring-servelet.xml

<?xml version="1.0" encoding="GBK"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core"
xmlns:p="http://cxf.apache.org/policy" xmlns:ss="http://www.springframework.org/schema/security"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/policy http://cxf.apache.org/schemas/policy.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> 
<!-- 使用CGLIB自动创建代理Bean -->
<aop:aspectj-autoproxy proxy-target-class="true">
</aop:aspectj-autoproxy>

<context:annotation-config />
<context:component-scan base-package="com.suning.uras.admin.web" />

<!-- 登陆权限插件包注解 -->
<context:component-scan base-package="com.suning.uras.common" />

<mvc:annotation-driven />

<!-- mvc 登陆鉴权拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 需要拦截的URL -->
<mvc:mapping path="/*/**" />

<bean class="com.suning.uras.common.interceptor.AuthLoginInterceptor">
<!-- 登陆页面 -->
<property name="loginUrl" value="/login.htm" />
<!-- 放行URL配置 -->
<property name="excludeList">
<list>
<value>/login.htm</value>
<value>/logout.htm</value>
</list>
</property>
</bean>
</mvc:interceptor>
</mvc:interceptors>

<!--无权限异常处理页面 -->
<bean id="exceptionResolver"
class="com.suning.uras.common.exception.AuthRightFailedExceptionResolver">
<!--
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
-->
<property name="exceptionMappings">
<props>
<!-- 支持自定义异常跳转FTL页面或者响应JSON数据,格式要求:FTL页面以.ftl结尾,其他配置全部以JSON数据格式处理 -->
<!-- JSON格式,根据实际无权限结果码配置,如果不配置,默认返回{"errorCode":"no_right","errorMessage":"无权限访问"} -->
<!-- JSON格式数据支持JSONP,但是回调函数名称必须是callback-->
<!-- JSON配置参考:

-->
<prop key="com.suning.uras.common.exception.AuthRightFailedException">no_right.ftl</prop>
<prop key="com.suning.uras.common.exception.AuthRightJsonFailedException">{"code":"1001","message":"no right message"}</prop>
</props>
</property>
<property name="warnLogCategory" value="WARN"></property>
</bean>

<!--===================== view resovler ===================== -->
<bean id="viewResolver" abstract="true">
<property name="attributes">
<props>
<prop key="resRoot">@{resRoot}</prop>
<prop key="envName">@{envName}</prop>
<prop key="versionNo">@{appVersion}</prop>
<prop key="esbUrl">$[esbUrl]</prop>
<prop key="urasLoginUrl">$[uras.login.url]</prop>
</props>
</property>
</bean>

<!--freemarker页面解析器 -->
<bean id="freemarkerResolver"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"
parent="viewResolver">
<!--<property name="cache" value="true"/> -->
<property name="order" value="1" />
<property name="viewNames">
<array>
<value>*.ftl</value>
</array>
</property>
<!-- <property name="suffix" value=".ftl" /> -->
<property name="requestContextAttribute" value="request" />
<property name="exposeSpringMacroHelpers" value="true" />
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<property name="allowSessionOverride" value="true" />
<property name="contentType" value="text/html;charset=utf-8" /><!--编码 -->
<property name="viewClass"
value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
</bean>
<!-- ===================== view resolver end ====================== -->

<!-- 文件上传支持 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<property name="maxUploadSize">
<value>31457280</value><!-- 上传文件大小限制为30M,3*1024*1024 -->
</property>
<property name="maxInMemorySize">
<value>4096</value>
</property>
</bean>

<!-- 属性文件加载 -->
<bean id="webPropertyConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:conf/main-setting-web.properties</value>
</list>
</property>
<property name="placeholderPrefix" value="@{" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
</bean>

<!-- FreeMarker配置文件 -->
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<description>Required for Freemarker to work in web tier</description>
<property name="configuration" ref="freemarkerConfiguration" />
</bean>

<!-- FreeMarker配置文件 -->
<bean id="freemarkerConfiguration"
class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<description>Using the Config directly so we can use it outside the
web tier
</description>
<!-- 模板加载路径 -->
<property name="templateLoaderPaths">
<list>
<value>/WEB-INF/freemarker/</value>
<!-- <value>/WEB-INF/ftl_macro</value> -->
</list>
</property>
<property name="configLocation">
<value>classpath:conf/freemarker.properties</value>
</property>
<!--全局变量部分 -->
<property name="freemarkerVariables">

10460
<map>
<entry key="xml_escape" value-ref="fmXmlEscape" />
<entry key="html_escape" value-ref="fmHtmlEscape" />
<entry key="base" value="@{base}" />
<entry key="envName" value="@{envName}" />
<entry key="resRoot" value="@{resRoot}" />
<entry key="esbUrl" value="$[esbUrl]" />
<entry key="urasLoginUrl" value="$[uras.login.url]" />
<entry key="loginDesKey" value="$[login.password.des.key]" />
</map>
</property>
<property name="defaultEncoding" value="utf-8" />
</bean>

<!-- 针对xml文件里特殊字符转义 -->
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" />

<!-- 针对html文件里特殊字符转义 -->
<bean id="fmHtmlEscape" class="freemarker.template.utility.HtmlEscape" />

</beans>


拦截器的写法

/**
* 登陆鉴权拦截器<br>
* 〈功能详细描述〉
*
* @author 15061841
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class AuthLoginInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(AuthLoginInterceptor.class);

private static final String DEFAULT_LOGIN_URL = "/login.ftl";

/**
* 拦截未登陆跳转登陆页URL
*/
private String loginUrl;

/**
* 放行URL
*/
private List<String> excludeList;

@Autowired
private AuthRightService authRightService;

public String getLoginUrl() {
return loginUrl;
}

public void setLoginUrl(String loginUrl) {
this.loginUrl = loginUrl;
}

public List<String> getExcludeList() {
return excludeList;
}

public void setExcludeList(List<String> excludeList) {
this.excludeList = excludeList;
}

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LOGGER.info("AuthLoginInterceptor.preHandle enter.");
// 校验放行URL
String uri = request.getServletPath();
if (!CollectionUtils.isEmpty(excludeList) && excludeList.contains(uri)) {
return true;
}
// 请求参数
String reqParam = request.getQueryString();
if (StringUtils.isNotBlank(reqParam)) {
uri += "?" + reqParam;
}
// 1、获取cookie中的loginToken
String loginToken = "";
Cookie[] cookies = request.getCookies();
if (null != cookies && cookies.length > 0) {
loginToken = getLoginTokenFromCookie(cookies);
}
// 2、RSF调用中台接口校验loginToken对应的session信息,返回对应userId
String userId = authRightService.validateLoginSeesion(loginToken);

// 设置默认登陆页面地址
if (StringUtils.isBlank(loginUrl)) {
loginUrl = DEFAULT_LOGIN_URL;
}
// 3、如果登陆session合法则放行,否则跳转登录页面重新登录
boolean result = false;
if (StringUtils.isBlank(userId)) {
// 跳转登录页面
response.sendRedirect(request.getContextPath() + loginUrl + "?targetUri=" + URLEncoder.encode(uri, "UTF-8"));
} else {
request.setAttribute("userId", userId);
result = true;
}
return result;
}

/**
* 功能描述: 获取登陆Token<br>
* 〈功能详细描述〉
*
* @param loginToken
* @param cookies
* @return
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
private String getLoginTokenFromCookie(Cookie[] cookies) {
String loginToken = "";
for (Cookie cookie : cookies) {
if ("loginToken".equals(cookie.getName())) {
String cookieValue = cookie.getValue();
String[] cookieValues = cookieValue.split("\\|");
if (cookieValues.length > 1) {
loginToken = cookieValues[0];
break;
}
}
}
return loginToken;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
LOGGER.info("AuthLoginInterceptor.postHandle enter.");
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
LOGGER.info("AuthLoginInterceptor.afterCompletion enter.");
}

}


自定义登陆异常

/**
* 自定义鉴权异常Resolver处理<br>
* 〈功能详细描述〉
*
* @author 15061841
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class AuthRightFailedExceptionResolver extends SimpleMappingExceptionResolver {
private static final Logger logers = LoggerFactory.getLogger(AuthRightFailedExceptionResolver.class);

private static final String ERROR_JSON = "{\"resultCode\":\"no_right\",\"resultMsg\":\"无权限访问\"}";

private static final String LOGIN_FLAG_JSON_APPEND_BEGIN = "\"loginFlag\":\"1\",";

private static final String CALLBACK_STR = "callback";

@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
// response print json strings
String viewName = determineViewName(ex, request);

try {
// 判断是否鉴权失败异常
if (ex instanceof AuthRightFailedException) {
// 如果是FTL页面提示错误
Integer statusCode = determineStatusCode(request, viewName);
logers.info("enter doResolveException() authRightFailedException,viewName={},statusCode={}", viewName,
statusCode);
if (statusCode != null) {
applyStatusCodeIfPossible(request, response, statusCode);
}
if (StringUtils.isNotBlank(viewName) && viewName.endsWith(".ftl")) {
logers.info("doResolveException() authRightFailedException ready success!");
return getModelAndView(viewName, ex, request);
}
}
if (ex instanceof AuthRightJsonFailedException) {
logers.info("enter doResolveException() authRightJsonFailedException,viewName={}", viewName);
PrintWriter out = response.getWriter();
// 如果空并且是鉴权自定义异常 返回默认JSON格式
if (StringUtils.isBlank(viewName)) {
viewName = ERROR_JSON;
}
// 处理未登录返回标识
// 获取cookie中的loginToken,如果loginToken不存在则认为未登陆
String loginToken = getLoginTokenFromCookie(request.getCookies());
if ("null".equals(loginToken) || StringUtils.isBlank(loginToken)) {
response.addHeader("passport.login.flag", "1");
// 返回JSON串拼接未登录标识
String[] viewNames = viewName.split("\\{");
viewName = "{" + LOGIN_FLAG_JSON_APPEND_BEGIN + viewNames[1];
}

// 处理JSONP
viewName = handleJsonp(request, viewName);

logers.info("enter doResolveException() authRightJsonFailedException ready success,viewName={}",
viewName);
// 设置ContentType
response.setContentType("application/json");
// 设置UTF-8避免乱码
response.setCharacterEncoding("UTF-8");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
out.print(viewName);
out.close();

}
// 非鉴权失败异常 业务系统可自行定义Resolve处理
} catch (Exception e) {
logers.error("SimpleMappingExceptionJsonResolver.doResolveException() error", e);
}
return new ModelAndView();
}

/**
* 功能描述: <br>
* 〈功能详细描述〉
*
* @param request
* @param viewName
* @return
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
private String handleJsonp(HttpServletRequest request, String viewName) {
// 判断返回格式JSON还是JSONP
// URL或者参数包含callback即认为是JSONP,和H5业务系统约定JSONP服务的回调方法名必须为callback,
// java业务系统的JSON服务地址必须为xxx_callback开头.htm/do或xxx.htm/do?callback=callback
String callbackMehodName = CALLBACK_STR;
String reqURI = request.getRequestURI();
String reqParam = request.getQueryString();
if (StringUtils.isNotBlank(reqURI) && reqURI.contains("_callback")) {
// 截取 _callback*到.do或.htm之间的字符串认为是JSONP回调函数的方法名
int end = reqURI.indexOf(".do");
if(end == -1) {
end = reqURI.indexOf(".htm");
}
int begin = reqURI.indexOf("_callback");
callbackMehodName = reqURI.substring(begin + 1, end);
return callbackMehodName + "(" + viewName + ")";
}

if (StringUtils.isNotBlank(reqParam)
&& (reqParam.contains("callback=callback") || reqParam.contains(CALLBACK_STR))) {
// 获取JSONP回调函数的方法名
callbackMehodName = request.getParameter(CALLBACK_STR);
return callbackMehodName + "(" + viewName + ")";
}
return viewName;
}

/**
*
* 功能描述: 从cookie中获取loginToken<br>
* 〈功能详细描述〉
*
* @param cookies
* @return
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
private String getLoginTokenFromCookie(Cookie[] cookies) {
String loginTokenValue = "";
if (null != cookies && cookies.length > 0) {
for (Cookie c : cookies) {
if ("loginToken".equals(c.getName())) {
loginTokenValue = c.getValue();
break;
}
}
}
// loginToken格式为token串|userId
return loginTokenValue.split("\\|")[0];
}

}


自定义异常

/**
* 〈一句话功能简述〉<br>
* 〈功能详细描述〉
*
* @author 15061841
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class AuthRightFailedException extends RuntimeException {
/**
*/
private static final long serialVersionUID = 6533990418559037407L;

public AuthRightFailedException() {
// 添加自身构造器
}

public AuthRightFailedException(String message) {
super(message);
}

public AuthRightFailedException(String message, Throwable cause) {
super(message, cause);
}

public AuthRightFailedException(Throwable cause) {
super(cause);
}
}


AuthRightJsonFailedException
public class AuthRightJsonFailedException extends RuntimeException {
/**
*/
private static final long serialVersionUID = 6533990418559037407L;

public AuthRightJsonFailedException() {
super();
}

public AuthRightJsonFailedException(String message) {
super(message);
}

public AuthRightJsonFailedException(String message, Throwable cause) {
super(message, cause);
}

public AuthRightJsonFailedException(Throwable cause) {
super(cause);
}
}


登出功能 步骤 1.清理当前服务端的loginToken 并且 把Cookie值清空

/**
*
* 功能描述: 退出登录<br>
* 〈功能详细描述〉
*
* @param response
* @param request
* @param callback
* @return
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
@RequestMapping("/logout_{callback}.do")
public String logout(HttpServletResponse response, HttpServletRequest request,
@PathVariable("callback") String callback) {
// 获取cookie中loginToken
String loginTokenValue = getLoginTokenFromCookie(request.getCookies());

// 清理服务端的loginToken
LoginResponse rsp = loginBusiness.logout(loginTokenValue);
if (null != rsp && LOGIN_SUCCESS.equals(rsp.getResultCode())) {
// 清除cookie信息
// 设置登录的cookie空
setCookie(null, response, null);
}

return ajaxJsonp(response, gson.toJson(rsp), callback);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: