У меня есть веб-приложение Spring MVC, защищенное с помощью Spring Secuirty, и оно настроено с использованием аннотаций Java, это классы конфигурации безопасности приложения My Spring MVC
package seguridad;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
@Configuration
@EnableWebSecurity
//@EnableWebMvcSecurity
public class SeguridadConfiguracion extends WebSecurityConfigurerAdapter {
@Autowired
private AutenticarProvider autenticador;
@Override
protected void configure( HttpSecurity http ) throws Exception
{
http
.authenticationProvider(autenticador)
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/img/**").permitAll()
.antMatchers("/sound/**").permitAll()
.antMatchers("/fonts/**").permitAll()
.antMatchers("/ajax/**").permitAll()
.antMatchers("/php/**").permitAll()
.antMatchers("/xml/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login/login")
.permitAll()
.and()
.logout()
.permitAll()
.logoutSuccessUrl("/login/login?logout")
.and()
.csrf().disable();
}
}
Мой AuthProvider
@Component
public class AutenticarProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String name = null;
String password = null;
Authentication auth = null;
boolean pruebaLDAP = false;
try {
name = authentication.getName();
password = authentication.getCredentials().toString();
if (name.equals("user") && password.equals("MyPassword"))
{
List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority("PERMISO_PRIMERO"));
grantedAuths.add(new SimpleGrantedAuthority("PERMISO_MODIFICAR_PERMISO"));
grantedAuths.add(new SimpleGrantedAuthority("PERMISO_CONSULTAR_PERMISO"));
auth = new UsernamePasswordAuthenticationToken(name, password, grantedAuths);
}
} catch (AuthenticationException e) {
e.printStackTrace();
throw e;
}
return auth;
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
Это мой класс контроллера метода Restful веб-службы, который я хочу вызвать. Метод получает строку JSON, затем я получаю значения, которые хочу, из строки JSON, а затем присваиваю эти значения объекту POJO, а затем возвращаю объект
@Controller
@RequestMapping("/jsp/")
public class InicioControlador {
@RequestMapping(value = "changeNameAfter", method = RequestMethod.POST)
public @ResponseBody
Person methodChangeStringPro(@RequestBody final String json, Model model)
throws IOException {
ObjectMapper mapper = new ObjectMapper();
Map<String, String> StringValues;
StringValues = mapper.readValue(json, HashMap.class);
String stringId = StringValues.get("id");
String name = StringValues.get("name");
System.out.println("EL STRING ID vale " + stringId);
System.out.println("EL name vale " + name);
int realId = Integer.parseInt(stringId);
String newName = name + "KEK";
realId = realId + 1;
Person person = new Person();
person.setName(newName);
person.setId(realId);
return person;
}
}
И это код из моего приложения для Android, где я пытаюсь вызвать этот метод
Мой основной класс деятельности
public class MainActivity extends AbstractAsyncActivity {
protected static final String TAG = MainActivity.class.getSimpleName();
// ***************************************
// Activity methods
// ***************************************
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initiate the request to the protected service
final Button submitButton = (Button) findViewById(R.id.submit);
submitButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new FetchSecuredResourceTask().execute();
}
});
}
// ***************************************
// Private methods
// ***************************************
private void displayResponse(Person response) {
Toast.makeText(this, response.getName(), Toast.LENGTH_LONG).show();
}
// ***************************************
// Private classes
// ***************************************
private class FetchSecuredResourceTask extends AsyncTask<Void, Void, Person> {
private String username;
private String password;
@Override
protected void onPreExecute() {
showLoadingProgressDialog();
// build the message object
EditText editText = (EditText) findViewById(R.id.username);
this.username = editText.getText().toString();
editText = (EditText) findViewById(R.id.password);
this.password = editText.getText().toString();
}
@Override
protected Person doInBackground(Void... params) {
final String url = "http://10.0.2.2:8080/ProyectoServidor/jsp/changeNameAfter";
// Populate the HTTP Basic Authentitcation header with the username
// and password
HttpAuthentication authHeader = new HttpBasicAuthentication(username, password);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAuthorization(authHeader);
requestHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
//Set OBJECT to send
Person personToSend = new Person();
personToSend.setId(23);
personToSend.setName("Prueba");
HttpEntity entityPerson = new HttpEntity(personToSend, requestHeaders);
try {
// Make the network request
Log.d(TAG, url);
ResponseEntity<Person> response = restTemplate.exchange(url, HttpMethod.POST,
entityPerson, Person.class);
return response.getBody();
} catch (HttpClientErrorException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
return new Person();
} catch (ResourceAccessException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
return new Person();
}
}
@Override
protected void onPostExecute(Person result) {
dismissProgressDialog();
displayResponse(result);
}
}
Мой класс AbstractAsyncActivity
public class AbstractAsyncActivity extends Activity {
protected static final String TAG = AbstractAsyncActivity.class.getSimpleName();
private ProgressDialog progressDialog;
private boolean destroyed = false;
// ***************************************
// Activity methods
// ***************************************
@Override
protected void onDestroy() {
super.onDestroy();
destroyed = true;
}
// ***************************************
// Public methods
// ***************************************
public void showLoadingProgressDialog() {
this.showProgressDialog("Loading. Please wait...");
}
public void showProgressDialog(CharSequence message) {
if (progressDialog == null) {
progressDialog = new ProgressDialog(this);
progressDialog.setIndeterminate(true);
}
progressDialog.setMessage(message);
progressDialog.show();
}
public void dismissProgressDialog() {
if (progressDialog != null && !destroyed) {
progressDialog.dismiss();
}
}
}
Я думаю, что проблема в этой строке из моего класса Main Activity
// Populate the HTTP Basic Authentitcation header with the username
// and password
HttpAuthentication authHeader = new HttpBasicAuthentication(username, password);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAuthorization(authHeader);
requestHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
//Set OBJECT to send
Person personToSend = new Person();
personToSend.setId(23);
personToSend.setName("Prueba");
HttpEntity entityPerson = new HttpEntity(personToSend, requestHeaders);
try {
// Make the network request
Log.d(TAG, url);
ResponseEntity<Person> response = restTemplate.exchange(url, HttpMethod.POST,
entityPerson, Person.class);
return response.getBody();
} catch (HttpClientErrorException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
return new Person();
} catch (ResourceAccessException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
return new Person();
}
Поскольку ОШИБКА, которую я получаю в своем LogCat,
10-16 00:33:51.054: E/AndroidRuntime(1481): Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [modelo.Person] and content type [text/html;charset=ISO-8859-1]
Я следовал этому руководству, но адаптировал его для своих нужд https://github.com/spring-projects/spring-android-samples/tree/master/spring-android-basic-auth
Я использую следующие библиотеки
jackson-core-asl-1.9.11.jar
jackson-mapper-asl-1.9.13.jar
spring-android-core-1.0.0.RELEASE.jar
spring-android-rest-template-1.0.1.RELEASE.jar
EDIT Пользователь @ravindra classNotFoundError был вызван тем, что я использовал jackson-core-asl-1.9.11.jar
вместо jackson-core-2.6.1.jar
после того, как добавил этот .JAR, а этот jackson-annotations-2.6.1.jar
исключение класса не найдено было устранено. Но у меня все еще есть исходная ошибка 10-16 04:44:37.524: E/AndroidRuntime(1349): Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [modelo.Person] and content type [text/html;charset=ISO-8859-1]
, которая заставила меня задать этот вопрос.
Это изменения, которые я сделал, и когда я думаю, что это проблема
// Populate the HTTP Basic Authentitcation header with the username
// and password
HttpAuthentication authHeader = new HttpBasicAuthentication(username, password);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAuthorization(authHeader);
requestHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
// Set OBJECT to send
Person personToSend = new Person();
personToSend.setId(23);
personToSend.setName("Prueba");
HttpEntity<Person> entityPerson = new HttpEntity<Person>(personToSend, requestHeaders);
try {
String json = "";
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("id", "2");
jsonObject.accumulate("name", "hola");
json = jsonObject.toString();
// Make the network request
Log.d(TAG, url);
ResponseEntity<Person> response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<Object>(requestHeaders), Person.class);
return response.getBody();
Я пытался использовать MappingJackson2HttpMessageConverter
в качестве своего конвертера, как это предлагается здесь в подобных вопросах:
Заставить Spring RestTemplate использовать XmlConverter и Не удалось извлечь ответ: не найден подходящий HttpMessageConverter для типа ответа, но все же я получаю та же ошибка
но все же я получаю ту же ошибку `10-16 04:44:37.524: E/AndroidRuntime (1349): вызвано: org.springframework.web.client.RestClientException: не удалось извлечь ответ: не найден подходящий HttpMessageConverter для типа ответа [ modelo.Person] и тип контента [text/html;charset=ISO-8859-1]
РЕДАКТИРОВАТЬ 2:
Я изменил аннотации своего контроллера и добавил produces = "application/json"
в метод RequestMappin следующим образом.
@RequestMapping(value = "changeNameAfter", method = RequestMethod.POST, produces = "application/json")
public @ResponseBody
Person methodChangeStringPro(@RequestBody final String json, Model model)
throws IOException {
Но все же это дает мне ту же ошибку.
E/AndroidRuntime(1349): Caused by: org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [modelo.Person] and content type [text/html;charset=ISO-8859-1]