2

我想在我的 J2EE 项目中包含 SSO。我正在尝试找到一个解决方案,它不需要我的应用程序服务器以外的其他服务器。

这是环境:

  • Glassfish v3.1.2
  • 2 个使用 Spring MVC / Security 的相同项目(比如说 project1 和 project2)

项目实施什么:

  • 一个简单的ajax登录表单
  • 具有登录和测试方法的控制器:

    @Controller
    public class ProjectController {
        public static final String REMEMBER_ME_ACTIVE = "on";
    
        @Autowired
        SecurityContextRepository repository;
    
        @Autowired
        RememberMeServices rememberMeServices;
    
        @RequestMapping(value = "/login", method = RequestMethod.GET)
        public Object login(HttpServletRequest request, HttpServletResponse response) {
            System.out.println("[GET] login");
            System.out.println(SecurityContextHolder.getContext().getAuthentication());
            System.out.println(request.getSession().getId());
    
            return new ModelAndView("login");
        }
    
        @RequestMapping(value = "/login", method = RequestMethod.POST)
        @ResponseBody
        public Object login(@RequestParam("j_username") String username, 
                            @RequestParam("j_password") String password,
                            @RequestParam("_spring_security_remember_me") String rememberMe,
                            HttpServletRequest request, HttpServletResponse response) {
            System.out.println("[POST] login");
            System.out.println(SecurityContextHolder.getContext().getAuthentication());
            System.out.println(request.getSession().getId());
    
            try {
    
                UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
    
                SecurityContext context = SecurityContextHolder.getContext();
    
                context.setAuthentication(token);
                repository.saveContext(context, request, response);
    
                if (REMEMBER_ME_ACTIVE.equals(rememberMe)) {
                    rememberMeServices.loginSuccess(request, response, token);
                }
    
                return "OK";
            }
            catch (BadCredentialsException e) {
                return "BadCredentialsException";
            }
            catch (Exception e) {
                e.printStackTrace();
    
                return "Exception : " + e.getMessage();
            }
        }
    
        @RequestMapping(value = "/test", method = RequestMethod.GET)
        public Object test(HttpServletRequest request, HttpServletResponse response) {
            System.out.println("[GET] test");
            System.out.println(SecurityContextHolder.getContext().getAuthentication());
            System.out.println(request.getSession().getId());
    
            return new ModelAndView("test");
        }
    }
    
  • 弹簧安全.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/security"
              xmlns:beans="http://www.springframework.org/schema/beans"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://www.springframework.org/schema/beans
                       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                       http://www.springframework.org/schema/security
                       http://www.springframework.org/schema/security/spring-security-3.1.xsd">
        <!-- security config -->
        <http auto-config="false" use-expressions="true" >
            <http-basic/>
    
            <intercept-url pattern="/login" access="hasRole('ROLE_ANONYMOUS')"/>
    
            <intercept-url pattern="/**" access="hasAnyRole('ROLE_USER')" />
    
            <form-login login-page="/login"
                        login-processing-url="/spring/login"
                        authentication-failure-url="/login"
                        default-target-url="/"
                        always-use-default-target="true" />
    
            <remember-me services-ref="tokenBasedRememberMeServices"
                         key="XXXXXX_1234567890"
                         use-secure-cookie="true" />
    
            <logout logout-url="/spring/logout"
                    invalidate-session="false"
                    logout-success-url="/login" />
    
            <session-management invalid-session-url="/login" session-fixation-protection="newSession">
                <concurrency-control max-sessions="3"
                                     error-if-maximum-exceeded="false"
                                     expired-url="/login"
                                     session-registry-ref="sessionRegistry" />
            </session-management>
        </http>
    
        <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
    
        <!-- authentication config -->
        <authentication-manager>
            <authentication-provider ref="userAuthenticationProvider"/>
        </authentication-manager>
    
        <beans:bean id="userAuthenticationProvider" class="be.xxx.spring.security.UserAuthenticationProvider" />
    
        <beans:bean id="tokenBasedRememberMeServices" class="be.xxx.spring.security.TokenBasedRememberMeServices">
            <beans:constructor-arg name="key" value="XXXXXX_1234567890"/>
            <beans:constructor-arg name="userDetailsService" ref="userDetailsService"/>
        </beans:bean>
    
        <beans:bean id="userDetailsService" class="be.xxx.spring.security.UserDetailsService" />
    </beans:beans>
    

到目前为止,我发现 Glassfish 支持此处所写的 SSO,但它似乎无法与 Spring Security 一起使用。在 project1 中登录时,我看不到 JSESSIONIDSSO。因此,当我启动 project2 时,它会向我发送登录表单...还尝试在 web.xml 中指定相同的领域名称,但没有更改。

经过一番谷歌搜索,我发现了一些关于 PreAuthenticationFilter 的东西,但我真的不知道如何用这个实现 SSO 解决方案。

你能帮我找出解决办法吗?

谢谢,

4

1 回答 1

0

如果项目相同,您始终可以使用粘性会话并在项目之间共享会话。

于 2014-04-15T10:42:45.523 回答