使用后端Spring Security Java EE服务器和前端iOS Objective-C客户端进行身份validation

我想validation在Java EE服务器后端连接到他的iOS应用程序上的用户。 在这里,你可以find我的spring安全configuration后端:

<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <http auto-config="true" use-expressions="true"> <intercept-url pattern="/home.mediator" access="permitAll" /> <intercept-url pattern="/loginInvalid.security" access="permitAll" /> <intercept-url pattern="/logout*" access="permitAll" /> <intercept-url pattern="/user**" access="hasRole('ROLE_USER')"/> <intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')"/> <intercept-url pattern="/*" access="isAuthenticated()" /> <form-login login-page="/home.mediator" default-target-url="/loginValid.security" authentication-failure-url="/loginInvalid.security" /> <logout invalidate-session="true" logout-success-url="/logoutSuccess.security" logout-url="/logout.do"/> </http> <authentication-manager> <authentication-provider user-service-ref="customUserDetailsService"> </authentication-provider> </authentication-manager> </beans:beans> 

这完美地在后台Web应用程序的浏览器上工作。 但问题是,当我访问我的后端Java EE服务器与我的iOS客户端C客户端进行身份validation过程是这样的:

  NSString *login = self.loginTextField.text; NSString *password = self.passwordTextField.text; NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8080/myJeeServer/j_spring_security_check"]]; [request setHTTPMethod:@"POST"]; NSString *post =[[NSString alloc] initWithFormat:@"j_username=%@&j_password=%@",login,password]; [request setHTTPBody:[post dataUsingEncoding:NSUTF8StringEncoding]]; NSHTTPURLResponse *urlResponse = nil; NSError *err; [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&err]; NSLog(@"Request : %@",request); NSLog(@"Response : %d",urlResponse.statusCode); NSLog(@"Error : %d",err.code); 

我已经得到了每一个HTTP响应状态码到200,我不能检查身份validation是成功还是根据iOS客​​户端的失败。 也许这种方式是用Spring安全后端和Objective-C客户端前端实现身份validation的错误方式,但是我在networking上没有find任何其他方法。 有人可以帮我用这个安全用例吗? 用Objective-C和Spring安全性validation用户的最佳方法是什么?

感谢您的回答。

亲爱,

我忘了把这个老话题的解决scheme放在一个面向同样情况的开发者的可能解决scheme之下:

  • iOS上的login示例客户端通过HTTP使用弹簧安全身份validation:

– (IBAction)connect:(UIButton *)sender {

  // Get login and password values NSString *login = self.loginTextField.text; NSString *password = self.passwordTextField.text; // Check if they are not empty before HTTP call if([login isEqualToString:@""] || [password isEqualToString:@""]) { self.loginResponse.text = @"Please select a login and a password before connect."; return; } else { self.userLogin = login; self.userPassword = password; } // Prepare request for login NSString *restRequest =[[NSString alloc] initWithFormat:@"%@/rest/%@",IP_SERVER,REST_LOGIN_OPERATION]; NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:[NSURL URLWithString:restRequest]]; [request setHTTPMethod:@"POST"]; NSString *post =[[NSString alloc] initWithFormat:@"j_username=%@&j_password=%@&submit=Login",self.userLogin,self.userPassword]; [request setHTTPBody:[post dataUsingEncoding:NSUTF8StringEncoding]]; // start the animation if it's not already going [self.spinner startAnimating]; dispatch_queue_t loginQ = dispatch_queue_create("endoServerLoginQueue", NULL); dispatch_async(loginQ, ^(){ // call Web Service REST on EndoServer for login NSHTTPURLResponse *urlResponse = nil; NSError *err; NSData *urlData =[NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&err]; // Log async call request NSLog(@"[%@ %@] Request for customer login : %@",NSStringFromClass([self class]), NSStringFromSelector(_cmd), request); // When we have the results, use main queue to display them dispatch_async(dispatch_get_main_queue(), ^{ // Parse data NSString *str=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding]; // Log async call response NSLog(@"[%@ %@] Response status code for doctor login : %d",NSStringFromClass([self class]), NSStringFromSelector(_cmd), urlResponse.statusCode); NSLog(@"[%@ %@] Response body for doctor login : (doctor id = %@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), str); NSLog(@"[%@ %@] Error code for doctor login : %d",NSStringFromClass([self class]), NSStringFromSelector(_cmd), err.code); if(urlResponse.statusCode == 200) { [self.logoutButton setEnabled:YES]; NSLog(@"[%@ %@] Connection Success for Customer login (%@) and Password (%@).",NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.userLogin,self.userPassword); // Save login and password in user preferences NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults]; [userPreferences setObject:self.userLogin forKey:USER_LOGIN_KEY]; [userPreferences setObject:self.userPassword forKey:USER_PASSWORD_KEY]; [userPreferences setInteger:[str integerValue] forKey:USER_ID_KEY]; [userPreferences synchronize]; // Go to Home screen view str = [NSString stringWithFormat:@"Welcome %@ ! ",self.userLogin]; [self performSegueWithIdentifier:@"goToHomePage" sender:self]; } if(err.code == -1004) { str = @"Server is shutdown, please try later or contact administrator."; NSLog(@"[%@ %@] Error message : %@",NSStringFromClass([self class]), NSStringFromSelector(_cmd), str); } self.loginResponse.text = str; // makes UIKit calls, so must be main thread [self.spinner stopAnimating]; // stop the animation }); }); 

}

  • 具有自定义身份validation处理程序的弹簧安全configuration

    …..

     <context:annotation-config /> <context:component-scan base-package="com....." /> .... <!-- Add Rest API access for mobile devices --> <http pattern="/rest/**" entry-point-ref="authenticationEntryPoint" use-expressions="true"> <intercept-url pattern="/rest/login" access="hasRole('ROLE_CUSTOMER')" /> <intercept-url pattern="/rest/customer/**" access="hasRole('ROLE_CUSTOMER')"/> <intercept-url pattern="/rest/logout" access="isAuthenticated()" /> <form-login login-processing-url="/rest/login" authentication-success-handler-ref="customAuthenticationSuccessHandler" authentication-failure-handler-ref="customAuthenticationFailureHandler"/> <logout success-handler-ref="customLogoutSuccessHandler" logout-url="/rest/logout" invalidate-session="true"/> </http> .... 

和处理程序实现的示例:

 @Component(value = "customAuthenticationSuccessHandler") public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { private static final Logger LOGGER = Logger.getLogger(CustomAuthenticationSuccessHandler.class); @Autowired private IUserRepository userRepository; @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { if (hasRoleCustomer(authentication)) { String username = authentication.getName(); User user = userRepository.findByUsername(username); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().print(user.getId()); LOGGER.info("Authentication Success for customer : "+user.getUsername()+", with id : "+user.getId()); } else { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.getWriter().print("Access Denied, please contact the administrator."); LOGGER.info("Access denied for customer : "+authentication.getName()); } response.getWriter().flush(); } 

其他所需的处理程序应根据您的业务需求以相同的方式执行。

Interesting Posts