Browse Source

切换企业

git-svn-id: svn+ssh://10.10.101.21/source/platform/platform-b2b@1144 f3bf4e98-0cf0-11e4-a00c-a99a8b9d557d
administrator 10 years ago
parent
commit
cbae2de069

+ 18 - 4
src/main/java/com/uas/platform/b2b/controller/AuthenticationController.java

@@ -4,6 +4,7 @@ import javax.servlet.http.HttpSession;
 
 import org.springframework.http.HttpStatus;
 import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.ResponseBody;
@@ -11,20 +12,33 @@ import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestController;
 
 import com.uas.platform.b2b.model.User;
+import com.uas.platform.b2b.model.UserInfo;
 import com.uas.platform.b2b.support.SystemSession;
 
 @RestController
 @RequestMapping("/authentication")
 public class AuthenticationController {
-	
+
 	@RequestMapping(method = RequestMethod.GET, headers = "Accept=application/json")
 	@ResponseBody
 	@ResponseStatus(value = HttpStatus.OK)
-	public User getAuthentication(Authentication authentication, HttpSession session) {
+	public UserInfo getAuthentication(Authentication authentication, HttpSession session) {
 		if (authentication == null) {
 			return null;
 		}
-		return SystemSession.getUser();
+		return new UserInfo(SystemSession.getUser());
 	}
-	
+
+	/**
+	 * 切换企业
+	 * 
+	 * @param enUU
+	 */
+	@RequestMapping(value = "/{enUU}")
+	@ResponseBody
+	public void switchEnterprise(@PathVariable("enUU") long enUU) {
+		User user = SystemSession.getUser();
+		user.setCurrentEnterprise(enUU);
+	}
+
 }

+ 5 - 0
src/main/java/com/uas/platform/b2b/dao/SigninLogDao.java

@@ -1,6 +1,8 @@
 package com.uas.platform.b2b.dao;
 
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
 import org.springframework.stereotype.Repository;
 
 import com.uas.platform.b2b.model.SigninLog;
@@ -8,4 +10,7 @@ import com.uas.platform.b2b.model.SigninLog;
 @Repository
 public interface SigninLogDao extends JpaRepository<SigninLog, Long> {
 
+	@Query("from SigninLog s where s.id=(select max(l.id) from SigninLog l where l.userUU = :userUU)")
+	public SigninLog findLast(@Param("userUU") long userUU);
+	
 }

+ 33 - 16
src/main/java/com/uas/platform/b2b/filter/SecurityInterceptor.java

@@ -150,30 +150,47 @@ public class SecurityInterceptor extends AbstractSecurityInterceptor implements
 		Object user = request.getSession().getAttribute("user");
 		if (user != null)
 			SystemSession.setUser((User) user);
-		else {
+		else {// login by remember-me
+				// spring remember-me通过客户端的SPRING_SECURITY_REMEMBER_ME_COOKIE和数据库的PERSISTENT_LOGINS匹配
 			Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
 			if (authentication != null && authentication.isAuthenticated()) {
-				User authedUser = userService.findUserByUserUU(Long.parseLong(authentication.getName()));
-				authedUser.setCurrentEnterprise();
-				Set<Role> roles = authedUser.getRoles();
-				if (!authedUser.isSys() && !CollectionUtils.isEmpty(roles)) {
-					for (Role role : roles) {
-						if (role.isSys()) {// 超级账号
-							authedUser.setIssys(Constant.YES);
-							break;
-						}
-					}
-				}
-				authedUser.setIp(AgentUtils.getIp(request));
+				User authedUser = loginByRememberMe(request, authentication);
 				request.getSession().setAttribute("user", authedUser);
 				SystemSession.setUser(authedUser);
-				// 记录登录日志
-				SitePreference preference = getDefaultSitePreferenceForDevice(this.deviceResolver.resolveDevice(request));
-				signinLogService.save(new SigninLog(authedUser, preference, AgentUtils.getIp(request), true));
 			}
 		}
 	}
 
+	/**
+	 * spring remember-me验证通过之后的登录处理
+	 * 
+	 * @param request
+	 * @param authentication
+	 * @return
+	 */
+	private User loginByRememberMe(HttpServletRequest request, Authentication authentication) {
+		User authedUser = userService.findUserByUserUU(Long.parseLong(authentication.getName()));
+		if (authedUser.getEnterprises().size() > 1) {
+			SigninLog log = signinLogService.findLast(authedUser.getUserUU());
+			authedUser.setCurrentEnterprise(log.getEnUU());
+		} else
+			authedUser.setCurrentEnterprise();
+		Set<Role> roles = authedUser.getRoles();
+		if (!authedUser.isSys() && !CollectionUtils.isEmpty(roles)) {
+			for (Role role : roles) {
+				if (role.isSys()) {// 超级账号
+					authedUser.setIssys(Constant.YES);
+					break;
+				}
+			}
+		}
+		authedUser.setIp(AgentUtils.getIp(request));
+		// 记录登录日志
+		SitePreference preference = getDefaultSitePreferenceForDevice(this.deviceResolver.resolveDevice(request));
+		signinLogService.save(new SigninLog(authedUser, preference, AgentUtils.getIp(request), true));
+		return authedUser;
+	}
+
 	private SitePreference getDefaultSitePreferenceForDevice(Device device) {
 		if (device == null) {
 			return null;

+ 12 - 0
src/main/java/com/uas/platform/b2b/model/User.java

@@ -230,6 +230,18 @@ public class User implements Serializable {
 			this.enterprise = this.enterprises.iterator().next();
 	}
 
+	public void setCurrentEnterprise(long enUU) {
+		if (this.enterprises != null && this.enterprises.size() > 0)
+			for (Enterprise enterprise : enterprises) {
+				if (enterprise.getUu() == enUU) {
+					this.enterprise = enterprise;
+					break;
+				}
+			}
+		if (this.enterprise == null)
+			setCurrentEnterprise();
+	}
+
 	public Set<Role> getRoles() {
 		return roles;
 	}

+ 26 - 0
src/main/java/com/uas/platform/b2b/model/UserInfo.java

@@ -1,10 +1,13 @@
 package com.uas.platform.b2b.model;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
+import org.springframework.util.CollectionUtils;
 
 /**
  * 用户简单信息,前台程序使用
@@ -29,6 +32,19 @@ public class UserInfo {
 			}
 			this.role = sb.toString();
 		}
+		if (!CollectionUtils.isEmpty(user.getEnterprises())) {
+			Enterprise current = user.getEnterprise();
+			List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
+			for (Enterprise enterprise : user.getEnterprises()) {
+				Map<String, Object> map = new HashMap<String, Object>();
+				map.put("enName", enterprise.getEnName());
+				map.put("uu", enterprise.getUu());
+				if (enterprise.equals(current))
+					map.put("current", true);
+				list.add(map);
+			}
+			this.enterprises = list;
+		}
 	}
 
 	public static Page<UserInfo> getUserInfo(Page<User> page) {
@@ -53,6 +69,8 @@ public class UserInfo {
 
 	private String role;
 
+	private List<Map<String, Object>> enterprises;
+
 	public Long getUserUU() {
 		return userUU;
 	}
@@ -101,4 +119,12 @@ public class UserInfo {
 		this.role = role;
 	}
 
+	public List<Map<String, Object>> getEnterprises() {
+		return enterprises;
+	}
+
+	public void setEnterprises(List<Map<String, Object>> enterprises) {
+		this.enterprises = enterprises;
+	}
+
 }

+ 8 - 0
src/main/java/com/uas/platform/b2b/service/SigninLogService.java

@@ -11,4 +11,12 @@ public interface SigninLogService {
 	 */
 	public void save(SigninLog log);
 
+	/**
+	 * 查找最近一次登录日志
+	 * 
+	 * @param userUU
+	 * @return
+	 */
+	public SigninLog findLast(long userUU);
+
 }

+ 5 - 0
src/main/java/com/uas/platform/b2b/service/impl/SigninLogServiceImpl.java

@@ -18,4 +18,9 @@ public class SigninLogServiceImpl implements SigninLogService {
 		signinLogDao.save(log);
 	}
 
+	@Override
+	public SigninLog findLast(long userUU) {
+		return signinLogDao.findLast(userUU);
+	}
+
 }

+ 62 - 8
src/main/java/com/uas/platform/b2b/support/CustomAuthenticationSuccessHandler.java

@@ -2,6 +2,10 @@ package com.uas.platform.b2b.support;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.servlet.ServletException;
@@ -9,6 +13,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.mobile.device.Device;
 import org.springframework.mobile.device.DeviceResolver;
 import org.springframework.mobile.device.LiteDeviceResolver;
@@ -21,6 +26,7 @@ import org.springframework.security.web.savedrequest.SavedRequest;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
+import com.uas.platform.b2b.model.Enterprise;
 import com.uas.platform.b2b.model.Role;
 import com.uas.platform.b2b.model.SigninLog;
 import com.uas.platform.b2b.model.User;
@@ -28,19 +34,22 @@ import com.uas.platform.b2b.service.SigninLogService;
 import com.uas.platform.b2b.service.UserService;
 import com.uas.platform.core.model.Constant;
 import com.uas.platform.core.util.AgentUtils;
+import com.uas.platform.core.util.serializer.FlexJsonUtils;
 
 public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
 
 	@Autowired
 	private UserService userService;
-	
+
 	@Autowired
 	private SigninLogService signinLogService;
 
+	private final static String paramEN = "t_enuu";
+
 	private RequestCache requestCache = new HttpSessionRequestCache();
-	
+
 	private final DeviceResolver deviceResolver;
-	
+
 	public CustomAuthenticationSuccessHandler() {
 		this(new LiteDeviceResolver());
 	}
@@ -52,7 +61,22 @@ public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationS
 	@Override
 	public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response,
 			final Authentication authentication) throws ServletException, IOException {
-		logSession(request, authentication);
+		User user = userService.findUserByUserUU(Long.parseLong(authentication.getName()));
+		if (user.getEnterprises().size() > 1) {// need to choose enterprise
+			if (!chooseEnterprise(request, response, user)) {
+				response.setStatus(HttpStatus.MULTI_STATUS.value());
+				response.addHeader("Content-Type", "application/json; charset=utf-8");
+				PrintWriter printWriter = response.getWriter();
+				printWriter.append(FlexJsonUtils.toJsonArray(getEnterprises(user)));
+				printWriter.flush();
+				printWriter.close();
+				return;
+			}
+		} else {
+			user.setCurrentEnterprise();
+		}
+
+		logSession(request, user);
 
 		final SavedRequest savedRequest = requestCache.getRequest(request, response);
 
@@ -84,9 +108,7 @@ public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationS
 	 * @param request
 	 * @param authentication
 	 */
-	private void logSession(HttpServletRequest request, Authentication authentication) {
-		User user = userService.findUserByUserUU(Long.parseLong(authentication.getName()));
-		user.setCurrentEnterprise();
+	private void logSession(HttpServletRequest request, User user) {
 		Set<Role> roles = user.getRoles();
 		if (!CollectionUtils.isEmpty(roles)) {
 			for (Role role : roles) {
@@ -103,7 +125,7 @@ public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationS
 		signinLogService.save(new SigninLog(user, preference, AgentUtils.getIp(request), false));
 
 	}
-	
+
 	private SitePreference getDefaultSitePreferenceForDevice(Device device) {
 		if (device == null) {
 			return null;
@@ -117,4 +139,36 @@ public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationS
 		return SitePreference.NORMAL;
 	}
 
+	private boolean chooseEnterprise(final HttpServletRequest request, final HttpServletResponse response, User user) throws IOException {
+		String enUU = request.getParameter(paramEN);
+		boolean choosed = false;
+		if (enUU != null) {
+			for (Enterprise enterprise : user.getEnterprises()) {
+				if (enterprise.getUu().toString().equals(enUU)) {
+					user.setEnterprise(enterprise);
+					choosed = true;
+					break;
+				}
+			}
+		}
+		return choosed;
+	}
+
+	private List<Map<String, Object>> getEnterprises(User user) {
+		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
+		SigninLog log = signinLogService.findLast(user.getUserUU());
+		Long lastEn = null;
+		if (log != null)
+			lastEn = log.getEnUU();// 可以优先选中最近一次登录的企业
+		for (Enterprise enterprise : user.getEnterprises()) {
+			Map<String, Object> map = new HashMap<String, Object>();
+			map.put("enName", enterprise.getEnName());
+			map.put("uu", enterprise.getUu());
+			if (lastEn != null && enterprise.getUu().equals(lastEn))
+				map.put("isLast", true);
+			list.add(map);
+		}
+		return list;
+	}
+
 }

+ 1 - 1
src/main/java/com/uas/platform/b2b/support/CustomUserDetailsService.java

@@ -34,7 +34,7 @@ public class CustomUserDetailsService implements UserDetailsService {
 	@Autowired
 	private UserService userService;
 
-	static final String TEL_REGEXP = "^((\\(\\d{3}\\))|(\\d{3}\\-))?(13|15|18)\\d{9}$";
+	static final String TEL_REGEXP = "^((\\(\\d{3}\\))|(\\d{3}\\-))?(13|15|17|18)\\d{9}$";
 
 	static final String UU_REGEXP = "^\\d{4,}$";
 

+ 9 - 2
src/main/webapp/WEB-INF/views/normal/index.html

@@ -27,8 +27,15 @@
 							class="text-inverse"></span> <i class="fa fa-angle-down fa-fw"></i> </a>
 						<div class="dropdown-menu" style="padding: 15px; width: 180px;">
 							<ul class="list-unstyled">
-								<li><a href="#"><h6 class="text-info">{{userInfo.enName}}</h6></a></li>
-								<li class="divider" ng-show="userInfo.enName"></li>
+								<li class="dropdown-submenu">
+									<a href="#" class="dropdown-toggle none"><strong class="text-info">{{userInfo.enterprise.enName}}</strong></a>
+									<ul class="dropdown-menu" ng-if="userInfo.enSelect" style="top: -16px;">
+										<li class="text-muted text-bold" style="padding: 0 15px;"><i class="fa fa-cog fa-fw"></i>切换企业到:</li>
+										<li class="divider"></li>
+										<li ng-repeat="e in userInfo.enSelect" class="item-link"><a ng-click="switchto(e.uu)">{{e.enName}}</a></li>
+									</ul>
+								</li>
+								<li class="divider" ng-show="userInfo.enterprise"></li>
 								<li><a href="#"><i class="fa fa-user fa-fw"></i>
 										{{userInfo.userName}}(<strong class="text-warning">{{userInfo.userUU}}</strong>)
 								</a></li>

+ 17 - 0
src/main/webapp/WEB-INF/views/normal/signin.html

@@ -141,5 +141,22 @@
 	<!-- 消息提示框 End -->
 	<script type="text/javascript" src="static/lib/require.js"
 		data-main="static/js/signin/main.js"></script>
+	<script type="text/ng-template" id="chooseEnterprise.html">
+ 	<div class="modal-header">
+		<h3 class="modal-title">您的账号绑定了下列企业</h3>
+	</div>
+	<div class="modal-body">
+		<div class="radio" ng-repeat="enterprise in enterprises">
+		  <label>
+		    <input type="radio" name="choose" ng-model="$parent.choose" value="{{enterprise.uu}}" checked>{{enterprise.enName}}
+		  </label>
+		</div>
+		<p class="text-info"><i class="fa fa-fw fa-warning"></i>请选择其中一个企业登录</p>
+	</div>
+	<div class="modal-footer">
+		<button class="btn btn-primary" ng-click="login(choose)" type="button">登录</button>
+		<button class="btn btn-default" ng-click="cancel()" type="button">取消</button>
+	</div>
+	</script>
 </body>
 </html>

+ 6 - 0
src/main/webapp/resources/css/index.css

@@ -356,6 +356,12 @@ a.none:hover {
 	color: #999;
 }
 
+ul>li.item-link>a {
+	padding: 10px 15px;
+	margin: 0 5px;
+	border-bottom: 1px dotted #ddd;
+}
+
 .throughline {
   	position: relative;
 }

+ 3 - 0
src/main/webapp/resources/js/common/services.js

@@ -130,6 +130,9 @@ define([ 'angular', 'toaster' ], function(angular) {
 				});
 				request.error(uncacheSession);
 				return request;
+			},
+			reSignin : function(enUU) {
+				return $http.get(rootPath + '/authentication/' + enUU);
 			}
 		};
 	}]).factory('SnapshotService', ['$http', 'BaseService', function($http, BaseService) {

+ 18 - 0
src/main/webapp/resources/js/index/app.js

@@ -229,6 +229,19 @@ define([ 'toaster', 'charts', 'ngTable', 'common/services', 'service/Purc', 'ser
 		$scope.isAuthed = AuthenticationService.isAuthed();
 		$scope.userInfo = {};
 		AuthenticationService.getAuthentication().success(function(data) {
+			if(data.enterprises) {
+				data.enterprise = data.enterprises[data.enterprises.length - 1];
+				if(data.enterprises.length > 1) {
+					var enSelect = [];
+					angular.forEach(data.enterprises, function(e){
+						if(e.current)
+							data.enterprise = e;
+						else
+							enSelect.push(e);
+					});
+					data.enSelect = enSelect;
+				}
+			}
 			$scope.userInfo = data;
 			if (data == null || !data.uu)
 				$scope.isAuthed = false;
@@ -238,6 +251,11 @@ define([ 'toaster', 'charts', 'ngTable', 'common/services', 'service/Purc', 'ser
 				$window.location.reload();
 			});
 		};
+		$scope.switchto = function(enUU) {// 切换企业
+			AuthenticationService.reSignin(enUU).success(function(){
+				$window.location.reload();
+			});
+		};
 		
 		$scope.addFavorite = function(){
 			var url = encodeURI(window.location.href); 

+ 34 - 3
src/main/webapp/resources/js/signin/app.js

@@ -1,10 +1,10 @@
-define([ 'toaster', 'services' ], function() {
+define([ 'toaster', 'ui.bootstrap', 'services' ], function() {
 	'use strict';
-	var app = angular.module('myApp', [ 'toaster', 'common.services' ]);
+	var app = angular.module('myApp', [ 'toaster', 'ui.bootstrap', 'common.services' ]);
 	app.init = function() {
 		angular.bootstrap(document, [ 'myApp' ]);
 	};
-	app.controller('AuthCtrl', ['$scope', '$window', '$location', 'toaster', 'AuthenticationService', 'SessionService', function($scope, $window, $location, toaster, AuthenticationService, SessionService) {
+	app.controller('AuthCtrl', ['$scope', '$window', '$location', 'toaster', 'AuthenticationService', 'SessionService', '$modal', function($scope, $window, $location, toaster, AuthenticationService, SessionService, $modal) {
 		$scope.loading = false;
 		$scope.user = {
 			j_username : SessionService.getCookie('J_USERNAME'),
@@ -24,6 +24,23 @@ define([ 'toaster', 'services' ], function() {
 					if(!url || url == '' || url.indexOf('/signin') > 0)
 						url = './';
 					$window.location.href = _url || url;
+				} else if(status == 207 && responseText instanceof Array) {// multi
+					$scope.loading = false;
+					$modal.open({
+						templateUrl: 'chooseEnterprise.html',
+						controller: 'ChooseEnterpriseCtrl',
+						size: 'sm',
+						resolve: {
+							enterprises: function() {
+								return responseText;
+							}
+						}
+					}).result.then(function(enUU){
+						if (enUU) {
+							user.t_enuu = enUU;
+							$scope.login(user);
+						}
+					});
 				}
 			}).error(function(responseText) {
 				$scope.loading = false;
@@ -54,6 +71,20 @@ define([ 'toaster', 'services' ], function() {
 		};
 		loginAndRedirect();
 	}]);
+	app.controller('ChooseEnterpriseCtrl', ['$scope', '$modalInstance', 'enterprises', function($scope, $modalInstance, enterprises){
+		$scope.choose = enterprises[enterprises.length -1].uu;
+		angular.forEach(enterprises, function(e){
+			if(e.isLast)
+				$scope.choose = e.uu;
+		});
+		$scope.enterprises = enterprises;
+		$scope.cancel = function() {
+			$modalInstance.close();
+		};
+		$scope.login = function(uu) {
+			$modalInstance.close(uu);
+		};
+	}]);
 	app.controller('NoticeCtrl', ['$scope', 'SnapshotService', function($scope, SnapshotService){
 		SnapshotService.getNotice(3, function(data){
 			$scope.notices = data;

+ 2 - 0
src/main/webapp/resources/js/signin/main.js

@@ -6,6 +6,7 @@ require.config({
 		'angular' : 'lib/angular/angular.min',
 		'ngAnimate': 'lib/angular/angular-animate.min',
 		'toaster' : 'lib/angular/angular-toaster.min',
+		'ui.bootstrap' : 'lib/angular/ui-bootstrap-tpls.min',
 		'services' : 'js/common/services'
 	},
 	shim : {
@@ -14,6 +15,7 @@ require.config({
 		},
 		'ngAnimate' : ['angular'],
 		'toaster' : ['angular', 'ngAnimate'],
+		'ui.bootstrap' : [ 'angular' ],
 		'services': ['angular']
 	}
 });