我們使用Eclipse Kepler IDE來開發我們的GWT應用程序,並且已經使用Ant腳本長時間部署到Tomcat容器。我們最近決定改用Hudson CI服務器來簡化GWT編譯和部署過程。我們遇到的問題是,當我們允許Eclipse執行它自己的連續構建時,然後執行GWT編譯/部署,我們的應用程序按預期工作。然而,當我們使用外部的javac程序編譯,無論是從一個獨立的JDK或使用Eclipse的編譯器(org.eclipse.jdt.core.JDTCompilerAdapter
),我們收到以下錯誤信息:爲什麼我會收到以下錯誤? 「沒有定義類型的唯一bean:期望單個匹配的bean但發現3」
Error creating bean with name 'loginServiceImpl' defined in file [/opt/tomcat/webapps/ROOT##10616/WEB-INF/classes/com/company/ribeye/server/service/LoginServiceImpl.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.security.authentication.AuthenticationManager]: : No unique bean of type [org.springframework.security.authentication.AuthenticationManager] is defined: expected single matching bean but found 3: [org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0, org.springframework.security.authentication.ProviderManager#0, org.springframework.security.authenticationManager]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.security.authentication.AuthenticationManager] is defined: expected single matching bean but found 3: [org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0, org.springframework.security.authentication.ProviderManager#0, org.springframework.security.authenticationManager]
我們沒有使用任何類型的依賴管理的,但Eclipse似乎處理java編譯沒有問題,我們不會遇到這個錯誤。當我們使用Ant任務和javac進行編譯時,我只想強調這個錯誤。同樣,即使使用Eclipse自己的捆綁編譯器,我們也會遇到問題。我還想補充一點,我不是Java開發人員,但是我是開發團隊的DevOps經理,所以CI服務器和部署策略屬於我的領域。我有一點Java知識,並且仍在學習,所以如果這是非常簡單的事情,我提前道歉。
這裏是我的相關代碼(未列出的所有進口,爲簡潔起見):
package com.company.ribeye.server.service;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
@Controller
@RequestMapping("/login")
public class LoginServiceImpl extends GWTController implements LoginService {
private static final long serialVersionUID = 1L;
private final AuthenticationManager authenticationManager;
private final UserDao userDao;
private final UserPreferenceDao userPreferenceDao;
@Autowired
public LoginServiceImpl(AuthenticationManager authenticationManager, UserDao userDao, UserPreferenceDao userPreferenceDao) {
this.authenticationManager = authenticationManager;
this.userDao = userDao;
this.userPreferenceDao = userPreferenceDao;
}
@Override
public ApplicationData getApplicationData() {
ApplicationData ap = new ApplicationData();
SimpleDateFormat df = new SimpleDateFormat("yyyy");
ap.setCurrentYear(Integer.parseInt(df.format(new Date())));
ap.setLoggedIn(false);
if (!ServerContext.isProductionServer() && ServerContext.isDevServer()) {
Pair<String, String> login = ServerContext.getDevAutoLogin();
ap.setDevModeAutoUsername(login.getA());
ap.setDevModeAutoPassword(login.getB());
}
if (ServerContext.getSession().getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY) == null) {
return ap;
}
User user = ServerContext.getCurrentUser();
if (user == null) {
return ap;
}
ApplicationContext ctx = ServerContext.getApplicationContext();
if (user.isPortalUser()) {
CustomerDao customerDao = (CustomerDao) ctx.getBean("customerDaoImpl");
user.setCustomer(customerDao.getById(user.getCustomerId()));
} else if (user.isVendorUser()) {
VendorDao vendorDao = (VendorDao) ctx.getBean("vendorDaoImpl");
user.setVendor(vendorDao.getById(user.getVendorId()));
}
ap.setLoggedIn(true);
ap.setDashDatabaseConnection(DashDataSourceContextHolder.getDatabaseType());
ap.setBuildNumber(ServerContext.getBuildNumber());
ap.setBuildDate(ServerContext.getBuildDate());
ap.setNextReleaseDate(ServerContext.getNextReleaseDate());
ap.setCurrentUser(user);
ap.setUserLinks(userPreferenceDao.getUserLinks(user.getId()));
ap.setMyContacts(userPreferenceDao.getMyContacts());
if (!user.isSwitched()) {
UserDaoImpl.updateUserActivity(user.getId());
}
ap.setUserActivity(UserDaoImpl.getAllUserActivity());
SystemDao systemDao = (SystemDao) ctx.getBean("systemDaoImpl");
ap.setEntityLinkers(systemDao.getEntityLinkers());
PollUpdateData pud = new PollUpdateData(user.getId());
ap.setNotificationSummary(systemDao.getPollData(pud).getNotificationSummary());
ap.setNotificationEntityTypeColors(systemDao.getNotificationEntityTypeColors());
ap.setUserPreferences(userPreferenceDao.getPreferencesByGroupName(user.getId(), null));
ArgMap<FlagArg> flagArgs = new ArgMap<FlagArg>();
flagArgs.put(FlagArg.USER_ID, user.getId());
ap.setFlagDefinitions(Common.asArrayList(userPreferenceDao.getFlagDefinitions(flagArgs)));
DocumentDao documentDao = (DocumentDao) ctx.getBean("documentDaoImpl");
ap.setLogoImage(documentDao.getLogoImage());
return ap;
}
這裏是我們的applicationContext-security.xml文件的相關部分:
<authentication-manager alias="authenticationManager">
<authentication-provider ref="ldapAuthProvider" />
<authentication-provider user-service-ref="customUserDetailsService">
<password-encoder ref="passwordEncoder">
<salt-source ref="saltSource" />
</password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<beans:constructor-arg>
<beans:bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<beans:constructor-arg ref="contextSource" />
<beans:property name="userSearch">
<beans:bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<beans:constructor-arg index="0" value="" />
<beans:constructor-arg index="1" value="REDACTED" />
<beans:constructor-arg index="2" ref="contextSource" />
</beans:bean>
</beans:property>
</beans:bean>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<beans:constructor-arg ref="contextSource"/>
<beans:constructor-arg value="REDACTED" />
<beans:property name="groupRoleAttribute" value="cn" />
<beans:property name="searchSubtree" value="false" />
<beans:property name="convertToUpperCase" value="true" />
<beans:property name="rolePrefix" value="ROLE_" />
<beans:property name="groupSearchFilter" value="member={0}" />
<beans:property name="defaultRole" value="ROLE_DASH" />
</beans:bean>
</beans:constructor-arg>
and dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<context:component-scan base-package="com.company.ribeye.server.service" />
<context:component-scan base-package="com.company.ribeye.server.dao" />
<context:component-scan base-package="com.company.ribeye.server.util" />
<context:annotation-config />
<security:global-method-security pre-post-annotations="enabled" />
</beans>
customUserDetailsService,如要求:
package com.company.ribeye.server.spring;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
public class CustomUserDetailsService implements UserDetailsService {
private DataSource dataSource;
private JdbcTemplate sjt;
public DataSource getDataSource() {
return dataSource;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
RowMapper<User> mapper = new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
return new User(rs.getString("Login"), rs.getString("PasswordDigest"), rs.getBoolean("IsEnabled"), rs.getBoolean("IsEnabled"), true, true,
getAuthorities(rs));
}
};
User user;
String sql = "select top 1 u.ID, u.Login, u.PasswordDigest, u.CustomerID, u.VendorID, u.IsPortalSuperUser, ";
sql += "dbo.IsActive(u.StartDate, u.EndDate, getdate()) as IsEnabled from Users u ";
sql += "where u.Login = ? and PasswordDigest is not null";
try {
user = sjt.queryForObject(sql, mapper, username);
} catch (DataAccessException e) {
throw new UsernameNotFoundException(username);
}
return user;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
sjt = new JdbcTemplate(dataSource);
}
private List<GrantedAuthority> getAuthorities(ResultSet rs) throws SQLException {
final List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
if (rs.getInt("VendorID") > 0) {
authList.add(new SimpleGrantedAuthority("ROLE_COMPANY_DASH_USERS"));
return authList;
}
authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_USER"));
if (rs.getBoolean("IsPortalSuperUser")) {
authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_SUPERUSER"));
authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_BILLING"));
authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_OPERATIONS"));
return authList;
}
// if not a superuser, fetch account-level roles from database
RowMapper<List<GrantedAuthority>> mapper = new RowMapper<List<GrantedAuthority>>() {
@Override
public List<GrantedAuthority> mapRow(ResultSet rs, int rowNum) throws SQLException {
if (rs.getInt("Billing") > 0) {
authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_BILLING"));
}
if (rs.getInt("Operations") > 0) {
authList.add(new SimpleGrantedAuthority("ROLE_PORTAL_OPERATIONS"));
}
return authList;
}
};
String sql = "select sum(cast(Billing as int)) as Billing, sum(cast(Operations as int)) as Operations ";
sql += "from PortalUserRoles ";
sql += "where UserID = ?";
sjt.queryForObject(sql, mapper, rs.getInt("ID"));
return authList;
}
}
,您可以複製CustomUserDetailsService? – RanPaul 2014-10-10 20:56:09
已添加CustomUserDetailsService。 :) – LegendaryDude 2014-10-10 21:00:04
您的LoginServiceImpl似乎是一個控制器,並且它沒有@Controller註釋 – RanPaul 2014-10-11 00:01:28