1

开始使用 Spring Security 保护我的一些 resful 服务器资源。我的客户对请求使用 ajax (jquery ajax),我首先实现了登录功能。

我的 Jersey web 图层包括以下内容:

@Path("/login")
@Component
public class LoginResourceProvider extends ServiceResourceProvider {

    /*--- Static ---*/

    private final static ILogger logger = LogManager.getLogger(LoginResourceProvider.class);

    /*--- Members ---*/

    @Inject
    @Qualifier("authenticationManager")
    protected AuthenticationManager authenticationManager;

    @Inject
    protected SecurityContextRepository repository;

    @Inject
    protected RememberMeServices rememberMeServices;

    /*--- Constructors ---*/

    public LoginResourceProvider() {
    super("Login");
    }

    /*--- Public Methods ---*/

    @GET
    public void login() {
    }

    /**
     * A user login attempt
     * 
     * @param username
     *            The user name
     * @param password
     *            The password of the given user name
     * @param request
     * @param response
     * @return A JSON string, indicating if the login is successful
     */
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public String performLogin(@QueryParam("j_username") String username, @QueryParam("j_password") String password,
        @Context HttpServletRequest request, @Context HttpServletResponse response) {

    // Create a token
    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
    SecurityContext securityContext = SecurityContextHolder.getContext();

    try {
        // Attempting to authenticate the user
        Authentication auth = authenticationManager.authenticate(token);

        // Updating the SecurityContext, which represents the user's
        // secured, authenticated session
        securityContext.setAuthentication(auth);

        // If the user authenticates successfully then the authentication
        // storing the security context in the HttpSession between requests
        repository.saveContext(securityContext, request, response);

        // object is passed to the remember-me service
        rememberMeServices.loginSuccess(request, response, auth);

        // Successfully authenticated
        return "{\"status\": true}";

        // Bad Credentials
    } catch (BadCredentialsException ex) {
        return "{\"status\": false, \"error\": \"Bad Credentials\"}";
    }
    }
}

我的 security-context.xml 现在非常基础,足以测试我的登录过程:

<http use-expressions="true">
    <form-login />
    <remember-me />
    <intercept-url pattern="/**" access="permitAll" />
    <intercept-url pattern="/secured/**" access="isAuthenticated()" />
</http>

<authentication-manager alias="authenticationManager">
    <authentication-provider>
        <user-service>
            <user name="bob" password="bobspassword" authorities="ROLE_USER" />
        </user-service>
    </authentication-provider>
</authentication-manager>

我有两个问题:

  1. 这是一个好习惯吗?我的意思是,我在那里找不到很多用于 ajax 样式请求的“非自动”登录。

  2. 尝试将安全上下文保存到 SecurityContextRepository 时出现异常,在这一行中:

    repository.saveContext(securityContext, request, response);

当我尝试使用 bob 作为用户名和 bobspassword 密码登录时,身份验证进行得很顺利,但是在调试此特定行时,我跳到 ClassCastException 并显示以下消息:

$Proxy31 cannot be cast to org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper

任何帮助表示赞赏!

4

1 回答 1

1

好的,我想我明白了。

根据Spring 文档,身份验证是使用以下步骤完成的:

  1. 获取用户名和密码并组合成一个 UsernamePasswordAuthenticationToken 的实例(Authentication 接口的一个实例,我们之前看到过)。
  2. 令牌被传递给 AuthenticationManager 的一个实例进行验证。
  3. AuthenticationManager 在身份验证成功时返回一个完全填充的身份验证实例。
  4. 安全上下文是通过调用 SecurityContextHolder.getContext().setAuthentication(...) 建立的,传入返回的身份验证对象。

除了上述步骤之外,我还尝试通过将 SecurityContext 保存到 SecurityContextRepository 来将其存储在请求之间。在请求之间存储 SecurityContext 的责任应该落到 SecurityContextPersistenceFilter 身上,它又会调用这个操作,所以我不需要手动去做,我想我应该只坚持上面的 4 个步骤。

更新:我想我尝试自己实现 Spring-Security 已经为我实现的东西。我不建议采用这种方法,Spring-Security 提供了一种更简单的做法。

于 2012-07-31T08:46:07.603 回答