Server side: Spring boot + JWT Auth
Client: React app
I want to connect via websocket but whenever I try to do it I always get error in console:
WebSocket connection to 'ws://localhost:6060/ws/app/add' failed: Error during WebSocket handshake: Unexpected response code: 404
Backend:
1) Websocket configuration
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("http://localhost:6060")
.setAllowedOrigins("http://localhost:8082")
// .setAllowedOrigins("*")
.setHandshakeHandler(new DefaultHandshakeHandler(new TomcatRequestUpgradeStrategy()))
.withSockJS();
registry.addEndpoint("/add");
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
}
2) Controller for receiving:
#Controller
public class ChatController {
#MessageMapping("/send") // FROM FRONTEND TO HERE
#SendTo("/topic/public") // FROM HERE TO FRONTEND
public ChatMessage sendMessage(#Payload ChatMessage chatMessage) {
return chatMessage;
}
#MessageMapping("/add")
#SendTo("/topic/public")
public ChatMessage addUser(#Payload ChatMessage chatMessage,
SimpMessageHeaderAccessor headerAccessor) {
// Add username in web socket session
headerAccessor.getSessionAttributes().put("username", chatMessage.getSender());
return chatMessage;
}
}
3) Security Config
package com.winterrent.winterrent.configuration;
import com.winterrent.winterrent.security.JwtAuthenticationEntryPoint;
import com.winterrent.winterrent.security.JwtAuthenticationFilter;
import com.winterrent.winterrent.service.user.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
CustomUserDetailsService customUserDetailsService;
#Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
#Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
http
.cors()
.and()
.csrf()
.ignoringAntMatchers("/ws/**")
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**")
.permitAll()
.anyRequest()
.authenticated();
}
}
4) JWT Auth filter
package com.winterrent.winterrent.security;
import com.winterrent.winterrent.service.user.CustomUserDetailsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
/**
* JWT token got from the request, validated and based on it loads the user associated with the token and pass
* it to Spring Security
*/
public class JwtAuthenticationFilter extends OncePerRequestFilter {
#Autowired
private JwtTokenProvider tokenProvider;
#Autowired
private CustomUserDetailsService customUserDetailsService;
private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
String jwt = getJwtFromRequest(request);
if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
Long userId = tokenProvider.getUserIdFromJWT(jwt);
UserDetails userDetails = customUserDetailsService.loadUserById(userId);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception ex) {
LOGGER.error("Could not set user authentication in security context", ex);
}
filterChain.doFilter(request, response);
}
private String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
LOGGER.debug(request.getHeader("Sec-WebSocket-Protocol"));
if (Objects.nonNull(request.getHeader("Sec-WebSocket-Protocol"))) {
bearerToken = request.getHeader("Sec-WebSocket-Protocol");
return bearerToken.substring(15, bearerToken.length());
}
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7, bearerToken.length());
}
return null;
}
}
5) CORS settings
package com.winterrent.winterrent.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class WebMvcConfig implements WebMvcConfigurer {
private final long MAX_AGE_SECS = 3600;
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:6060")
.allowedOrigins("http://localhost:8082")
// .allowedOrigins("*")
.allowedMethods("HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE")
.allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method",
"Access-Control-Request-Headers", "Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")
.maxAge(MAX_AGE_SECS);
}
}
Client:
const wsx123 = new WebSocket('ws://localhost:6060/ws/app/add',
['Authorization', window.localStorage.getItem('accessToken')], ['Access-Control-Allow-Credentials', 'true']);
I tried many options, but really always 404...
Has anybody any idea?
Regards!
The issue was with really bad path (404 was not stupid error) -
'ws://localhost:6060/resources/ws'
Above was correct because I had resources context path set up.
Related
This question already has an answer here:
CORS Error: “requests are only supported for protocol schemes: http…” etc
(1 answer)
Closed 1 year ago.
I have a problem with the CORS. I have the following configuration of security:
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
CustomUserDetailsService userDetailsService;
#Autowired
private CustomJwtAuthenticationFilter customJwtAuthenticationFilter;
#Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
public void configure(HttpSecurity http) throws Exception {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
corsConfiguration.setAllowedOrigins(List.of("*"));
corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT","OPTIONS","PATCH", "DELETE"));
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setExposedHeaders(List.of("Authorization"));
http.csrf().disable()
.authorizeRequests()
.antMatchers("/helloadmin").hasRole("ADMIN")
.antMatchers("/hellouser").hasAnyRole("USER","ADMIN")
.antMatchers("/techshop/web/v1/product/save").hasRole("ADMIN")
.antMatchers("techshop/web/v1/product").hasAnyRole("USER", "ADMIN")
.antMatchers("techshop/web/v1/product/{id}").hasRole("ADMIN")
.antMatchers("/authenticate").permitAll().anyRequest().authenticated()
.and().exceptionHandling()
//if any exception occurs call this
.authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//Add a filter to validate the tokens with every request
http.addFilterBefore((Filter) customJwtAuthenticationFilter,
UsernamePasswordAuthenticationFilter.class);
}
}
And I have the following controllers:
#RestController
#RequestMapping(value = "")
public class AuthenticationController {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private CustomUserDetailsService customUserDetailsService;
#Autowired
private JwtUtil jwtUtil;
#PostMapping(path = "/authenticate", consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> createAuthenticationToken(#RequestBody AuthenticationRequest request) throws Exception {
try{
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
request.getUsername(), request.getPassword()));
} catch (DisabledException e) {
throw new Exception("USER_DISABLE", e);
} catch (BadCredentialsException e){
throw new Exception("INVALID_CREDENTIALS", e);
}
final UserDetails userDetails = customUserDetailsService.loadUserByUsername(request.getUsername());
final String token = jwtUtil.generateToken(userDetails);
return ResponseEntity.ok(new AuthenticationResponse(token));
}
}
And:
#RestController
#RequestMapping("techshop/web/v1")
public class ProductController {
#Autowired
private ProductServiceI productService;
#PostMapping(value = "/product/save", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> save(#RequestBody ProductDto request){
productService.save(request);
return ResponseEntity.ok(Boolean.TRUE);
}
#GetMapping(value = "/product", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> findAll(){
return ResponseEntity.ok(productService.findAll());
}
#PutMapping(value = "/product/{id}", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> updateProduct(#PathVariable("id") int id, #RequestBody ProductDto request){
productService.update(request, id);
return ResponseEntity.ok(Boolean.TRUE);
}
#DeleteMapping(value = "/product/{id}")
public ResponseEntity<Object> deleteById(#PathVariable("id") int id){
productService.deletedById(id);
return ResponseEntity.ok(Boolean.TRUE);
}
}
When I make the following request, the browser show the CORS problem:
let datos = {
username:"admin",
password:"admin"
}
const getToken = () => {
axios({
method: 'post',
url: 'localhost:8080/test',
data: datos
});
}
getToken()
enter image description here
I've tried everything, with the #CrosOrigin ("*") annotation, with lambdas, with a Bean WebConfig that extends from corsConfigurer, but nothing works.
I appreciate if you can help me.
Please try the following:
const getToken = () => {
axios({
method: 'post',
url: 'http://localhost:8080/test',
data: datos
});
}
I've started this multi chat thread alert system and I've successfully gotten multiple clients on the server, but when broadcasting the message to everyone, it only interacts with the initial client sending the message and the sever only, the other client does not receive the message.
Here are the codes I'm working with
Client 1
package popup;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class ClientJFrame extends javax.swing.JFrame {
static Socket s;
static DataInputStream din;
static DataOutputStream dout;
public ClientJFrame() {
super("Client 1");
initComponents();
}
private void alertButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
String msgout = "Alert client 1\n";
dout.writeUTF(msgout);
} catch (Exception e) {
}
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ClientJFrame().setVisible(true);
}
});
try {
s = new Socket("127.0.0.1", 111);
din = new DataInputStream(s.getInputStream());
dout = new DataOutputStream(s.getOutputStream());
String msgin = "";
while (true) {
msgin = din.readUTF();
messageArea.append(msgin);
JOptionPane.showMessageDialog(null, "BITCH WE ON FIRE");
s.close();
System.exit(0);
}
} catch (Exception e) {
}
}
// Variables declaration - do not modify
private javax.swing.JButton alertButton;
private javax.swing.JScrollPane jScrollPane1;
private static javax.swing.JTextArea messageArea;
// End of variables declaration
}
Server
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class TestJFrame extends javax.swing.JFrame {
static ServerSocket listener;
static Socket s;
private static final int PORT = 111;
public TestJFrame() {
super("Main");
initComponents();
}
public static class Handler extends Thread {
private final Socket socket;
private DataInputStream in;
private DataOutputStream out;
public Handler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
in = new DataInputStream(socket.getInputStream());
messageArea.append("in\n");
out = new DataOutputStream(socket.getOutputStream());
messageArea.append("Out\n");
} catch (IOException e) {
}
while (true) {
try {
String input = in.readUTF();
messageArea.append(input);
out.writeUTF("We on Fire!!!\n");
} catch (IOException ex) {
Logger.getLogger(TestJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public static void main(String args[]) throws IOException, InterruptedException {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new TestJFrame().setVisible(false);
createAndShowGUI();
}
});
listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
// Variables declaration - do not modify
private javax.swing.JButton alertButton;
private javax.swing.JScrollPane jScrollPane1;
private static javax.swing.JTextArea messageArea;
// End of variables declaration
}
When a client connects to the server, add him to a list, so you always know who's connected. The same goes for when he disconnects.
When a client sends a message, process it however you want, then iterate over the list of connected clients and send them the message.
Take a look at the observer pattern, I think it will help for your project.
I have a trouble with CORS configuration. I've followed few tutorials, videos on YT and I was looking for help here, on StackOverflow - but nothing helps me.
I have two backend projects (first one - Spring Boot 1.5.9 with OAuth2 and JWT, second one - Spring Boot 2.0.0 M7 with Spring Security 5 basic authentication) and my friend uses React for frontend. In both I have the same problem - when we want to login, server responses with 401 HTTP status and following message:
Failed to load http://localhost:8080/oauth/token: Response for preflight has invalid HTTP status code 401
Case 1 (Spring Boot 1.5.9 OAuth2 JWT)
In this project I have
SecurityConfig class that extends WebSecurityConfigurerAdapter
My implementation of AuthorizationServerConfigurerAdapter
And implementation of ResourceServerConfig
My ResourceServerConfig class looks like this:
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCES_IDS = "ResourceId";
private static final String SECURITY_REALM = "Spring Boot Realm";
private final TokenStore tokenStore;
#Autowired
public ResourceServerConfig(TokenStore tokenStore) {
this.tokenStore = tokenStore;
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCES_IDS)
.tokenStore(tokenStore);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(REGISTER_USER + "/**").permitAll()
.antMatchers(HttpMethod.GET, GEOTAGS_PATH + "/**").permitAll()
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll()
.and()
.httpBasic()
.realmName(SECURITY_REALM)
.and()
.csrf().disable().cors();
}
}
AuthorizationServerConfig:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final TokenStore tokenStore;
private final JwtAccessTokenConverter accessTokenConverter;
private final AuthenticationManager authenticationManager;
private final DataSource dataSource;
#Autowired
public AuthorizationServerConfig(TokenStore tokenStore,
JwtAccessTokenConverter accessTokenConverter,
AuthenticationManager authenticationManager,
#Qualifier("customDatasource") DataSource dataSource) {
this.tokenStore = tokenStore;
this.accessTokenConverter = accessTokenConverter;
this.authenticationManager = authenticationManager;
this.dataSource = dataSource;
}
#Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.jdbc(dataSource);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
final TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Collections.singletonList(accessTokenConverter));
endpoints.tokenStore(tokenStore)
.accessTokenConverter(accessTokenConverter)
.tokenEnhancer(enhancerChain)
.authenticationManager(authenticationManager);
}
}
And finally SecurityConfig:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String SIGNING_KEY = "Gz73RSOADKDFXzONqg3q";
private UserDetailsService customUserDetailsService;
private DataSource dataSource;
#Autowired
public void setCustomUserDetailsService(UserDetailsService customUserDetailsService) {
this.customUserDetailsService = customUserDetailsService;
}
#Autowired
public void setDataSource(#Qualifier("customDatasource") DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNING_KEY);
return converter;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.singletonList("*"));
configuration.setAllowedMethods(Collections.singletonList("*"));
configuration.setAllowedHeaders(Collections.singletonList("*"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
As you can see I use CorsConfigurationSource Bean but when we run javascript code which is in different Origin:
fetch('http://localhost:8080/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${window.btoa('eTaxiClientId:secret')}`
},
body: `username=${encodeURIComponent('Admin')}&password=${encodeURIComponent('pass')}&grant_type=password`
});
Server response with message that I described on the beginning.
I have also tried use my implementation of WebMvcConfigurerAdapter with overridden addCorsMappings method, I tried to permitAll HttpMethod.OPTIONS but browser always sends OPTIONS request witch is matched with 401 code.
Case 2 (Spring Boot 2)
In this project I tried to use basic Spring Security authorization system - without OAuth2 and JWT. And my configuration is:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final MyUserDetailsService userDetailsService;
private final DataSource dataSource;
public SecurityConfig(MyUserDetailsService userDetailsService,
#Qualifier("customDatasource") DataSource dataSource) {
this.userDetailsService = userDetailsService;
this.dataSource = dataSource;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.servletApi().and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/api/1").hasAuthority("USER")
.antMatchers("/api/2").hasAuthority("ADMIN")
.antMatchers("/api/3").hasAuthority("GUEST")
.and()
.anonymous().principal("guest").authorities("GUEST")
.and()
.formLogin().permitAll()
.successHandler(new CustomAuthenticationSuccessHandler())
.failureHandler(new CustomAuthenticationFailureHandler())
.and()
.logout()
.logoutSuccessUrl("/login")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling()
.and()
.rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository())
.and()
.headers()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.and()
.cors()
.and()
.csrf().disable();
// .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
#Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authenticationProvider());
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
#Bean
public PersistentTokenRepository tokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();
jdbcTokenRepositoryImpl.setDataSource(dataSource);
return jdbcTokenRepositoryImpl;
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedHeaders(Collections.singletonList("*"));
configuration.setAllowedOrigins(Collections.singletonList("*"));
configuration.setAllowedMethods(Collections.singletonList("*"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
And in this case when we run following code in JavaScript application:
const body = `username=${encodeURIComponent('admin')}&password=${encodeURIComponent('pass')}`;
const hashedCredentials = btoa('admin:pass');
return axios.post(`${process.env.REACT_APP_API_URL}/login`, body, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
// test oauth credentials
Authorization: `Basic ${hashedCredentials}`
}
})
.then(() => {
localStorage.setItem('user', hashedCredentials);
})
.then(() => {
const userCredentials = localStorage.getItem('user');
return axios.get(`${process.env.REACT_APP_API_URL}/api/2`, null, {
headers: {
Authorization: `Basic ${userCredentials}`
}
});
}).then(res => console.log(res)).catch(err => console.log(err));
OPTIONS request passes and we have status 200 response but as you can see we tried to redirect user to end point that is protected. But instead of displaying message on the screen, Spring Security redirects as to login page..
Summary
Have someone had such problem? Does someone see what we are doing wrong ? Why do we have problem in both projects? Is better (and safer) approach for user authentication?
I hope I haven't forgotten to describe something and I am looking forward for response. Cheers !
My first thread: Anything I try to store on database enters with value '0'
I solved that, but now I'm having another problem:
Why am I having this error when I try to login?
09-11 17:20:46.382 2577-5031/com.example.gustavo.loginregister D/NetworkSecurityConfig: No Network Security Config specified, using platform default
09-11 17:20:47.415 2577-5031/com.example.gustavo.loginregister E/Volley: [145] BasicNetwork.performRequest: Unexpected response code 404 for https://xxxxxxx.000webhostapp.com/Login.php
09-11 17:22:39.640 2577-6700/com.example.gustavo.loginregister E/Volley: [152] BasicNetwork.performRequest: Unexpected response code 404 for https://xxxxxxx.000webhostapp.com/Login.php
LoginActivity.java file:
package com.example.gustavo.loginregister;
import android.app.AlertDialog;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
public class LoginActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
final EditText edtEmail = (EditText) findViewById(R.id.edtEmail);
final EditText edtSenha = (EditText) findViewById(R.id.edtSenha);
final Button btnLogin = (Button) findViewById(R.id.btnLogin);
final TextView txtCadastreSe = (TextView) findViewById(R.id.txtCadastreSe);
txtCadastreSe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent registroIntent = new Intent(LoginActivity.this, RegisterActivity.class);
LoginActivity.this.startActivity(registroIntent);
}
});
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String email = edtEmail.getText().toString();
final String password = edtSenha.getText().toString();
Response.Listener<String> responseListener = new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonResponse = new JSONObject(response);
boolean success = jsonResponse.getBoolean("success");
if (success) {
String name = jsonResponse.getString("name");
String lastname = jsonResponse.getString("lastname");
Intent intent = new Intent(LoginActivity.this, UserAreaActivity.class);
intent.putExtra("name", name);
intent.putExtra("lastname", lastname);
intent.putExtra("email", email);
LoginActivity.this.startActivity(intent);
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this);
builder.setMessage("Login Failed")
.setNegativeButton("Retry",null)
.create()
.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
LoginRequest loginRequest = new LoginRequest(email, password, responseListener);
RequestQueue queue = Volley.newRequestQueue(LoginActivity.this);
queue.add(loginRequest);
}
});
}
}
LoginRequest.java file:
package com.example.gustavo.loginregister;
import com.android.volley.Response;
import com.android.volley.toolbox.StringRequest;
import java.util.HashMap;
import java.util.Map;
public class LoginRequest extends StringRequest {
private static final String LOGIN_REQUEST_URL="https://wavecheck.000webhostapp.com/Login.php";
private Map<String, String> params;
public LoginRequest(String email, String password, Response.Listener<String> listener){
super(Method.POST, LOGIN_REQUEST_URL, listener, null);
params = new HashMap<>();
params.put("email", email);
params.put("password", password);
}
#Override
public Map<String, String> getParams() {
return params;
}
}
Login.php file:
<?php
require("Password.php");
$con = mysqli_connect("localhost", "xxx", "xxx", "xxxx");
$email = $_POST["email"];
$password = $_POST["password"];
$statement = mysqli_prepare($con, "SELECT * FROM user WHERE email = ?");
mysqli_stmt_bind_param($statement, "s", $email);
mysqli_stmt_execute($statement);
mysqli_stmt_store_result($statement);
mysqli_stmt_bind_result($statement, $colUserID, $colName, $colLastname, $colEmail, $colPassword);
$response = array();
$response["success"] = false;
while(mysqli_stmt_fetch($statement)){
if (password_verify($password, $colPassword)) {
$response["success"] = true;
$response["name"] = $colName;
$response["lastname"] = $colLastname;
$response["email"] = $colEmail;
}
}
echo json_encode($response);
?>
When you visit https://wavecheck.000webhostapp.com/Login.php directly it doesn't return JSON. It returns a 404 error page "There's nothing here, yet.
This domain is ready to be registered.". This is a message from the host. Apparently you're using a FREE host, and the "wavecheck" subdomain isn't there. So you'd need to re-host your PHP script, or get in contact with the free host to figure out what happened.
I am having this form below which performs sometimes first action and sometimes last action instead of both the actions one after another continuously.
Form:
<html>
<head>
</head>
<body>
<script language="Javascript">
function OnButton1()
{
document.Form1.action = "http://localhost:8084/WorldCupFinal/finalsearching1";
document.Form1.target="_blank";
document.Form1.submit();
document.Form1.action = "http://localhost:8084/SemiFinal/finalsearching1";
document.Form1.target="_blank";
document.Form1.submit();
}
</script>
<form name="Form1" method="post" target="_blank">
File Name <input type="text" name="t1" size="10" ><br />
<INPUT type="button" value="Button1"
name=name onclick="OnButton1();" >
</form>
</body>
</html>
finalsearching1 is java servlet program which takes input as filename searches for a file in some system depending on the action(in my local host as well as in other IP address).
But this action is only performed only one time by my servlet. I want
to execute both actions one after another or is there any way that i can execute them concurrently which takes less time. This scenario is performed by me for 2 different buttons(2 actions). I want to perform it using a single button having single text box and multiple actions takes place.
I have searched a lot and i am finding it that this can be performed using AJAX or if possible using javascript.
Could you please provide me solution for it.
Thank you for your concern in advance.
Here is my finalsearching1 program code:
import static java.awt.SystemColor.window;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import static java.io.FileDescriptor.out;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Files;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import static org.apache.tomcat.jni.Shm.buffer;
import upload.UploadDownloadFileServlet;
#WebServlet(urlPatterns = {"/finalsearching1"})
public class finalsearching1 extends HttpServlet {
private static String name,name1;
private static int a=0,p=0;
int count=0;
static URL u;
static final int BUFFER_SIZE = 1024*1024;
static HttpServletResponse response;
private static void setContentType(HttpServletResponse response) {
throw new UnsupportedOperationException("Not supported yet.");
}
private static void doGet1(String m1, HttpServletRequest request, HttpServletResponse response) {
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = request.getParameter("t1");
if(fileName == null || fileName.equals("")){
throw new ServletException("File Name can't be null or empty");
}
File file = new File(request.getServletContext().getRealPath("")+File.separator+fileName);
if(!file.exists()){
throw new ServletException("File doesn't exists on server.");
}
System.out.println("File location on server::"+file.getAbsolutePath());
ServletContext ctx = getServletContext();
InputStream fis = new FileInputStream(file.getAbsolutePath());
String mimeType = ctx.getMimeType(file.getAbsolutePath());
response.setContentType(mimeType != null? mimeType:"application/octet-stream");
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
ServletOutputStream os = response.getOutputStream();
byte[] bufferData = new byte[1024*1024];
int read=0;
while((read = fis.read(bufferData))!= -1){
os.write(bufferData, 0, read);
}
os.flush();
os.close();
fis.close();
System.out.println("File downloaded at client successfully");
}
private static void sendFile(HttpServletResponse response, File clientFileName) throws IOException
{
ServletOutputStream op = null;
setContentType(response);
response.setHeader("Content-Disposition", "attachment; filename=\"" + clientFileName + "\"");
}
private static ServletFileUpload uploader = null;
public static void parseAllFiles(String parentDirectory,HttpServletRequest request,HttpServletResponse response) throws IOException, Exception {
PrintWriter pr=response.getWriter();
response.setContentType("text/html");
File[] filesInDirectory = new File(parentDirectory).listFiles();
if(filesInDirectory != null){
for (File f : filesInDirectory){
if(f.isDirectory()){
parseAllFiles(f.getAbsolutePath(),request,response);
}
else if(name.equalsIgnoreCase(f.getName()))
{
pr.println("File Found with path "+f.getParentFile()+"\\"+name);
String m1=f.getParentFile()+"\\"+name;
System.out.println("File to upload: " + m1);
response.setContentType("text/html");
File file = new File(m1);
System.out.println();
String ext = "."+FilenameUtils.getExtension(m1);
System.out.println(ext);
f = File.createTempFile("tmp",ext, new File("C:\\Users\\Pankaj\\Desktop\\JADE-all-4.3.3\\WorldCupFinal\\build\\web"));
String f1=f.getName();
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(m1);
out = new FileOutputStream(f);
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
System.out.println(c+" Hi");
}
finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
pr.write("Hi..........");
pr.write("<br>");
pr.write("Download "+name+"");
pr.write("<br>");
a++;
}
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
PrintWriter pr=response.getWriter();
name=request.getParameter("t1");
if(name == null || name.equals("")){
throw new ServletException("File Name can't be null or empty");
}
System.out.println("name: "+name);
System.out.println("Starting the execution of a project :");
response.setContentType("text/html");
File[] files = File.listRoots();
for(File f : files){
try {
System.out.println(f.getPath());
System.out.println("response:"+response);
parseAllFiles(f.getPath(),request,response);
} catch (Exception ex) {
Logger.getLogger(finalsearching1.class.getName()).log(Level.SEVERE, null, ex);
}
}
if(a==0)
pr.println("File Not Found");
pr.println("Starting the Execution in system 2nd");
}
public String getServletInfo() {
return "Short description";
}
}