/** * Copyright (c)2010-2011 Enterprise Website Content Management System(EWCMS), All rights reserved. * EWCMS PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * http://www.ewcms.com */ package com.ewcms.security.manage.service; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.dao.SaltSource; import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.security.authentication.encoding.PlaintextPasswordEncoder; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import com.ewcms.core.site.SiteFacable; import com.ewcms.core.site.model.Organ; import com.ewcms.security.manage.model.Authority; import com.ewcms.security.manage.model.Group; import com.ewcms.security.manage.model.User; import com.ewcms.security.manage.model.UserInfo; @Service public class UserService extends AbstractService implements UserServiceable{ private static final Logger logger = LoggerFactory.getLogger(UserService.class); private String defaultPassword = "666666"; @Autowired(required = false) private AuthenticationManager authenticationManager; @Autowired(required = false) private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder(); @Autowired(required = false) private SaltSource saltSource; @Autowired(required = false) private SiteFacable siteFac; @Override public String addUser(final String username,final String password, final boolean enabled,final Date accountStart,final Date accountEnd, final UserInfo userInfo, final Integer organId)throws UserServiceException { Organ organ = null; if (organId != null){ organ = siteFac.getOrgan(organId); } if(accountStart !=null && accountEnd != null ){ Assert.isTrue(accountEnd.getTime() > accountStart.getTime(),"account date start > end"); } if(hasUsername(username)){ throw new UserServiceException( messages.getMessage("UserService.usernameExist","username already exist")); } User user = new User(username,enabled,accountStart,accountEnd); UserInfo info = (userInfo != null ? userInfo : new UserInfo()); info.setUsername(username); if(info.getName() == null){ info.setName(username); } user.setUserInfo(info); user.setOrgan(organ); //初始用户密码 String newPassword = StringUtils.isBlank(password) ? defaultPassword : password; user.setPassword(newPassword); //创建UserDetails password不为空 UserDetails userDetails = createUserDetails(user); user.setPassword(passwordEncoder(userDetails, newPassword)); userDao.persist(user); return username; } /** * 得到存在的用户 * * 用户不存在抛出异常 * * @param username 用户名 * @return 用户对象 * @throws UserServiceException */ private User getExistUser(final String username)throws UserServiceException{ User user = userDao.get(username); if(user == null){ throw new UserServiceException(messages.getMessage( "GroupService.groupNotFound",new Object[]{username},"Can't found "+ username + " username")); } return user; } @Override public String updateUser(final String username, final boolean enabled,final Date accountStart, final Date accountEnd,final UserInfo userInfo, final Integer organId) throws UserServiceException{ Organ organ = null; if (organId != null){ organ = siteFac.getOrgan(organId); } if(accountStart !=null && accountEnd != null ){ Assert.isTrue(accountEnd.getTime() > accountStart.getTime(),"account date start > end"); } User user = getExistUser(username); user.setEnabled(enabled); user.setAccountStart(accountStart); user.setAccountEnd(accountEnd); user.setOrgan(organ); user.getUserInfo().setBirthday(userInfo.getBirthday()); user.getUserInfo().setEmail(userInfo.getEmail()); user.getUserInfo().setIdentification(userInfo.getIdentification()); user.getUserInfo().setMphone(userInfo.getMphone()); user.getUserInfo().setName(userInfo.getName()); user.getUserInfo().setPhone(userInfo.getPhone()); userDao.persist(user); return username; } @Override public User getUser(final String username) { return userDao.get(username); } @Override public void removeUser(final String username) { userDao.removeByPK(username); userCache.removeUserFromCache(username); } @Override public void activeUser(final String username)throws UserServiceException{ User user = getExistUser(username); user.setEnabled(true); } @Override public void inactiveUser(final String username)throws UserServiceException{ User user = getExistUser(username); user.setEnabled(false); userDao.persist(user); removeExpiredUserByUsername(username); } @Override public Set<Authority> addAuthoritiesToUser(String username,Set<String> names) throws UserServiceException{ User user = getExistUser(username); Set<Authority> newAuths =new HashSet<Authority>(); for(String name : names){ Authority newAuth = getAuthorityByName(name); if(!user.getAuthorities().contains(newAuth)){ newAuths.add(newAuth); } } user.getAuthorities().addAll(newAuths); userDao.persist(user); removeExpiredUserByUsername(username); return newAuths; } @Override public void removeAuthoritiesInUser(String username, Set<String> names) throws UserServiceException{ User user = getExistUser(username); Set<Authority> auths = new HashSet<Authority>(); for(Authority auth : user.getAuthorities()){ if(!names.contains(auth.getName())){ auths.add(auth); } } user.setAuthorities(auths); userDao.persist(user); removeExpiredUserByUsername(username); } @Override public Set<Group> addGroupsToUser(String username, Set<String> names) { User user = getExistUser(username); Set<Group> newGroups =new HashSet<Group>(); for(String name : names){ Group newGroup = getGroupByName(name); if(!user.getGroups().contains(newGroup)){ newGroups.add(newGroup); } } user.getGroups().addAll(newGroups); userDao.persist(user); removeExpiredUserByUsername(username); return newGroups; } @Override public void removeGroupsInUser(String username, Set<String> names) { User user = getExistUser(username); Set<Group> groups = new HashSet<Group>(); for(Group group : user.getGroups()){ if(!names.contains(group.getName())){ groups.add(group); } } user.setGroups(groups); userDao.persist(user); removeExpiredUserByUsername(username); } @Override public UserInfo getCurrentUserInfo()throws AuthenticationException{ Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (currentUser == null) { throw new AccessDeniedException("Can't change user info as no Authentication object found in context for current user."); } final String username = currentUser.getName(); User user = userDao.get(username); return user == null ? null : user.getUserInfo(); } @Override public void updateUserInfo(final UserInfo userInfo)throws AuthenticationException{ Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (currentUser == null) { throw new AccessDeniedException("Can't change user info as no Authentication object found in context for current user."); } final String username = currentUser.getName(); User user = userDao.get(username); if(user == null){ if(logger.isDebugEnabled()){ logger.debug("{} user is null",username); } return ; } user.getUserInfo().setBirthday(userInfo.getBirthday()); user.getUserInfo().setEmail(userInfo.getEmail()); user.getUserInfo().setIdentification(userInfo.getIdentification()); user.getUserInfo().setMphone(userInfo.getMphone()); user.getUserInfo().setName(userInfo.getName()); user.getUserInfo().setPhone(userInfo.getPhone()); userDao.persist(user); } @Override public void changePassword(final String oldPassword, final String newPassword) throws AuthenticationException { Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); if (currentUser == null) { throw new AccessDeniedException("Can't change password as no Authentication object found in context for current user."); } final String username = currentUser.getName(); if (this.authenticationManager != null) { if(logger.isDebugEnabled()){ logger.debug("Reauthenticating user '{}' for password change request.",username); } authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, oldPassword)); } else { if(logger.isDebugEnabled()){ logger.debug("No authentication manage set.Password won't be re-checked"); } } if(logger.isDebugEnabled()){ logger.debug("Changing password for user {}'", username); } UserDetails userDetails = loadUserByUsername(username); String encoder = passwordEncoder(userDetails, newPassword); userDao.updatePassword(username, encoder); SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(userDetails, encoder)); userCache.removeUserFromCache(username); } protected String passwordEncoder(UserDetails userDetails, String password) { Object salt = (saltSource == null ? null : saltSource.getSalt(userDetails)); return passwordEncoder.encodePassword(password, salt); } protected Authentication createNewAuthentication(UserDetails userDetails, String newPassword) { UsernamePasswordAuthenticationToken newAuthentication = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities()); newAuthentication.setDetails(userDetails); return newAuthentication; } @Override public void initPassword(final String username,final String password) throws AuthenticationException { UserDetails userDetails = this.loadUserByUsername(username); String encoder = passwordEncoder(userDetails, password); userDao.updatePassword(username, encoder); userCache.removeUserFromCache(username); } @Override public boolean hasUsername(String username) { User user = userDao.get(username); return user != null; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { UserDetails userDetails = userCache.getUserFromCache(username); if (userDetails != null) { if(logger.isDebugEnabled()){ logger.debug("userDetails has cache"); } return userDetails; } if(logger.isDebugEnabled()){ logger.debug("userDetails has not cache"); } User user = userDao.get(username); if (user == null) { throw new UsernameNotFoundException("not fonund " + username); } userDetails = createUserDetails(user); userCache.putUserInCache(userDetails); return userDetails; } /** * 通过PO User来创建Spring Security UserDetails * * @param user * @return UserDetails */ private UserDetails createUserDetails(final User user){ Assert.notNull(user,"user is null"); Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>(); Set<Authority> auths = user.getAuthorities(); if (auths != null) { if(logger.isDebugEnabled()){ logger.debug("loadding user authorities"); } for (Authority auth : auths) { authorities.add(new GrantedAuthorityImpl(auth.getName())); } } Set<Group> groups = user.getGroups(); if(groups != null){ for (Group group : groups) { if(logger.isDebugEnabled()){ logger.debug("lodding {} of group authorities",group.getName()); } authorities.addAll(groupAuthorities(group)); } } return new org.springframework.security.core.userdetails.User( user.getUsername(), user.getPassword(), user.isEnabled(), noExpired(user.getAccountStart(),user.getAccountEnd()), true, true, authorities); } /** * 判断输入的日期没有过去 * * 如果start=null并且end=null,则用户永远不过期。 * * @param start 开始日期 * @param end 结束日期 * @return 如 true 不过期 false 过期 */ protected boolean noExpired(final Date start,final Date end) { if(start == null && end == null){ return true; } boolean nonExpired = true; long now = System.currentTimeMillis(); if (start != null) { nonExpired = nonExpired && start.getTime() <= now; } if (end != null) { nonExpired = nonExpired && end.getTime() >= now; } return nonExpired; } /** * 得到用户组通用权限 * * 用户组本身也属于通用权限一部分,可以用户组可以实现ACL控制。 * * @param group 用户组对象 * @return 用户组通用权限组 */ protected Set<GrantedAuthority> groupAuthorities(final Group group) { Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>(); Set<Authority> auths = group.getAuthorities(); if (auths != null) { for (Authority auth : auths) { authorities.add(new GrantedAuthorityImpl(auth.getName())); } } authorities.add(new GrantedAuthorityImpl(group.getName())); return authorities; } public void setDefaultPassword(String defaultPassword) { this.defaultPassword = defaultPassword; } @Override public String getDefaultPassword(){ return this.defaultPassword; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } public void setPasswordEncoder(PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } public void setSaltSource(SaltSource saltSource) { this.saltSource = saltSource; } }