不明确的映射。无法映射***;已经映射了 *** bean 方法

问题描述 投票:0回答:1

多年之后,我们终于将 Spring 框架更新到最新版本,其中包括一些我已经能够解决的问题。但这个我似乎无法弄清楚。

我们有一个 LoginController,其中包含不同的映射,例如 LoginRedirect.do、ChangePassword.Do 等。但由于某种原因,当它尝试将 war 文件部署到 tomcat 时,我不断收到此错误消息:

原因:java.lang.IllegalStateException:不明确的映射。无法映射“customUserDetailsService2”方法 com.test.controller.LoginController#loginRedirect(ModelMap) 到 {GET [/login/LoginRedirect.do]}:已经有 'loginController' bean 方法 com.test.controller.LoginController#loginRedirect(ModelMap) 已映射。

我没有其他控制器具有这些映射,但这似乎是由我们的 customUserDetailsService2 bean 引起的。我们的 ApplicationContext-security.xml 有这个:

<beans:bean id="customAuthenticationProvider" class="com.test.security.CustomDaoAuthenticationProvider">
    <beans:property name="userDetailsService" ref="customUserDetailsService2"/>
</beans:bean>

<beans:bean id="customUserDetailsService2" class="com.test.controller.LoginController"/>

登录控制器看起来像这样:

package com.test.controller;

import com.test.dao.datasnap.ILoginDAO;
import com.test.dao.datasnap.IPublicMethodsDAO;
import com.test.dao.datasnap.IUtilDAO;
import com.test.exception.DataSnapException;
import com.test.model.BasicResult;
import com.test.model.LoginResponse;
import com.test.model.PDCUser;
import com.test.security.CustomUser;
import com.test.security.CustomUserDetailsService;
import com.test.security.Module;
import com.test.translations.UITranslationCache;
import com.test.util.Util;
import jakarta.servlet.http.HttpServletRequest;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
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.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Controller
@Scope("request")
@RequestMapping("login")
public class LoginController implements CustomUserDetailsService {
   
    /*
    * Autowired DAO for Login
    */
    @Autowired
    private ILoginDAO dataDAO;

    @Autowired
    private IUtilDAO utilDAO;
      
    @Autowired
    private IPublicMethodsDAO methodsDAO; 
    
    /*
     * Gets the current logged in user. 
     */
    @GetMapping(value="/GetUserName.do")
    public String printUser(ModelMap modelMap) {
           
        String name = Util.getUserName(); //get logged in username
        modelMap.put("data", name);
        return "ajax/json/dataresponse";   
    }

    //from the CustomUserDetailsService interface
    public UserDetails loadUserByUsernamePasswordAuthenticationToken(UsernamePasswordAuthenticationToken authentication)
               throws UsernameNotFoundException, DataAccessException {
    
        /*
        * Use the DAO to get the data we want. This is something we really want to delegate so that we can keep our controller code as small
        * as possible.
        */
            
        try {

            String username = authentication.getName();
            if (((username == null) || "".equals(username))) {
                throw new BadCredentialsException(UITranslationCache.GetUITranslation(16877, Util.GetCompanyLanguage(), "Username and/or password are not correct."));
            }

            LoginResponse returnObject = dataDAO.loginToPDC(authentication);
            PDCUser pdcUser = (PDCUser) returnObject.getDataObject();

            List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);

            /*
             * based on the settings retrieved from DataSnap, we set the appropriate authorities for the user
             */
            if (pdcUser != null && pdcUser.getModules() != null) {
                Iterator<Module> itr = pdcUser.getModules().iterator();
                while(itr.hasNext()) {
                    Module module = itr.next();
                    if (module.getGrantedauthority() != null) {
                        authList.add(new SimpleGrantedAuthority(module.getGrantedauthority()));
                    }
                }
            }
                    
            UserDetails user = null;            
            boolean enabled = true;         
            user = new CustomUser(
                    pdcUser.getUsername(),
                    pdcUser.getManNr(),
                    pdcUser.getPassword(),
                    enabled,
                    authList,
                    returnObject.getSessionId(),
                    pdcUser.getModules(),
                    pdcUser.getLanguageCode(),
                    pdcUser.getRememberMe(),
                    pdcUser.getPasswordExpired());

            return user;
        } catch (DataSnapException e) {
            throw new AuthenticationServiceException(e.getMessage());
        } catch (AuthenticationException e) {
            throw e;
        } catch (Exception e)   {
            e.printStackTrace();
        }
        return null;             
    }
    
    @ResponseStatus(value=HttpStatus.FORBIDDEN)
    @GetMapping(value = "/accessdenied.do")
    public ModelAndView accessDenied(ModelMap modelmap) {

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        List<Module> modules = Util.getModules();
        
        modelmap.put("modules", modules);
        modelmap.put("username", auth.getName());
        
        return new ModelAndView("accessdenied", modelmap); // logical view name -> accessdenied.jsp
        
    }
    
        
    @ResponseStatus(value=HttpStatus.UNAUTHORIZED)
    @GetMapping(value ="/LoginRedirect.do")
    public String loginRedirect(ModelMap modelmap) throws JSONException{

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("success", false);
        jsonObject.put("message", UITranslationCache.GetUITranslation(16878, Util.GetCompanyLanguage(), "User not authorized to view this page"));
        
        modelmap.put("data", jsonObject);
        
        return "ajax/json/dataresponse";
    }
    
    @GetMapping(value ="/LogoutAjax.do")
    public String logoutAjax(ModelMap modelmap) throws JSONException{

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("success", true);
        jsonObject.put("message", UITranslationCache.GetUITranslation(16879, Util.GetCompanyLanguage(), "User was succesfully logged out"));
        
        modelmap.put("data", jsonObject);
        
        return "ajax/json/dataresponse";
    }

    @GetMapping(value ="/ChangePassword.do")
    public String changePassword(@RequestParam(required = true, value = "oldpw") String oldpw,
                                 @RequestParam(required = true, value = "newpw") String newpw,
                                 ModelMap modelMap) throws DataSnapException {

        BasicResult result = utilDAO.ChangePassword(oldpw, newpw);

        modelMap.put("data", result.getResult());

        return "ajax/json/dataresponse";
    }
    
}

在 customUserDetailsService2 进行更改之前,LoginController 本身似乎映射了不同的方法。但这以前可以用,所以我有点迷失为什么现在不起作用了。

java spring maven
1个回答
0
投票

你的控制器很奇怪,它混合了职责。您的控制器既是控制器又不是控制器。将

UserDetailsService
移动到它自己的组件中,正如它应该的那样。
将控制器设置为请求范围也是没有意义的。

最后,由于

UserDetailsService

和 XML 中的声明,您最终得到 2 个实例(这也是错误告诉您的)。

@Controller

您修改后的 XML 配置

@Service public class MyCustomUserDetailsService implements CustomUserDetailsService { @Autowired private ILoginDAO dataDAO; //from the CustomUserDetailsService interface public UserDetails loadUserByUsernamePasswordAuthenticationToken(UsernamePasswordAuthenticationToken authentication) throws UsernameNotFoundException, DataAccessException { /* * Use the DAO to get the data we want. This is something we really want to delegate so that we can keep our controller code as small * as possible. */ try { String username = authentication.getName(); if (((username == null) || "".equals(username))) { throw new BadCredentialsException(UITranslationCache.GetUITranslation(16877, Util.GetCompanyLanguage(), "Username and/or password are not correct.")); } LoginResponse returnObject = dataDAO.loginToPDC(authentication); PDCUser pdcUser = (PDCUser) returnObject.getDataObject(); List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2); /* * based on the settings retrieved from DataSnap, we set the appropriate authorities for the user */ if (pdcUser != null && pdcUser.getModules() != null) { Iterator<Module> itr = pdcUser.getModules().iterator(); while(itr.hasNext()) { Module module = itr.next(); if (module.getGrantedauthority() != null) { authList.add(new SimpleGrantedAuthority(module.getGrantedauthority())); } } } UserDetails user = null; boolean enabled = true; user = new CustomUser( pdcUser.getUsername(), pdcUser.getManNr(), pdcUser.getPassword(), enabled, authList, returnObject.getSessionId(), pdcUser.getModules(), pdcUser.getLanguageCode(), pdcUser.getRememberMe(), pdcUser.getPasswordExpired()); return user; } catch (DataSnapException e) { throw new AuthenticationServiceException(e.getMessage()); } catch (AuthenticationException e) { throw e; } catch (Exception e) { e.printStackTrace(); } return null; } }

您的瘦身控制器

<beans:bean id="customAuthenticationProvider" class="com.test.security.CustomDaoAuthenticationProvider"> <beans:property name="userDetailsService" ref="customUserDetailsService2"/> </beans:bean> <beans:bean id="customUserDetailsService2" class="com.test.controller.MyCustomUserDetailsService"/>

© www.soinside.com 2019 - 2024. All rights reserved.