3

我在 Spring 3.1 中创建了一个简单的会话范围 bean。它应该让我可以轻松访问当前登录用户的公司。

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionData {

    private Company company;

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }
}

我在自定义身份验证提供程序的 authenticate() 方法中使用 Company 填充此 bean。

@Component(value = "authenticationProvider")
public class ProduxAuthenticationProvider implements AuthenticationProvider {

    private SessionData sessionData;
    private CompanyService companyService;

    @Autowired
    public ProduxAuthenticationProvider(SessionData sessionData, CompanyService companyService) {
        this.sessionData = sessionData;
        this.companyService = companyService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        // Authentication logic (token creation) removed for readability....

        Company company = companyService.findByUserProfile(profile);

        // Set company on session bean
        sessionData.setCompany(company);

        return token;
    }
}

然后我尝试访问 ManagementHomeController 中的 company 字段,该字段在身份验证成功完成后运行。

@Controller
@RequestMapping(value = "/manage/home")
public class ManagementHomeController {

    private CourseService userService;
    private CompanyService companyService;
    private SessionData sessionData;

    @Autowired
    public ManagementHomeController(CourseService userService, CompanyService companyService, SessionData sessionData) {
        this.userService = userService;
        this.companyService = companyService;
        this.sessionData = sessionData;
    }

    @RequestMapping(method = RequestMethod.GET)
    public String get(Model model) {
        model.addAttribute("mainContent", "content/managementHome");

        // sessionData.company is null here! Object id is same as in ProduxAuthenticationProvider

        return "main";
    }
}

不知何故,在 ManagementHomeController 中,SessionData 的公司字段为空,但它是同一个对象。我可以看到,因为 sessionData 的对象 ID 在 ProduxAuthenticationProvider 和 ManagementHomeController 中是相同的。

知道为什么 SessionData 在此过程中失去了它的公司吗?

4

1 回答 1

2

不完全确定这是否可行,但据我了解,因为您将会话范围的 bean 注入到过滤器中,该过滤器在调用 Spring Dispatcher servlet 之前调用,范围代理正常工作所需的某些请求属性可能尚未设置正确。

解决方法是将此逻辑移动到 Spring Interceptor 或在 web.xml中注册RequestContextListener

于 2012-11-11T00:05:44.143 回答