How to do a POST request from SAPUI5 controller to Java Servlet? - javascript

I have created a dynamic web project with a Tomcat 8.5 Server and then I created an index.html that do start my first view (a simple form for login). When I click the button for login start function onPress:
onPress : function() {
var user = this.getView().byId("userInput").getValue();
var pwd = this.getView().byId("passwordInput").getValue();
var request = {
un : user,
pw : pwd
};
$.post("LoginServlet", request, function() {
alert("Ciao");
});
}
I want to pass user and pwd to this servlet (LoginServlet)
public class LoginServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
try {
UserBean user = new UserBean();
user.setUserName(request.getParameter("un"));
user.setPassword(request.getParameter("pw"));
user = UserDAO.login(user);
/*if (user.isValid()) {
HttpSession session = request.getSession(true);
session.setAttribute("currentSessionUser", user);
response.sendRedirect("userLogged.jsp"); // logged-in page
}else
response.sendRedirect("invalidLogin.jsp"); // error page*/
} catch (Throwable theException) {
System.out.println(theException);
}
}
}
The error I am getting is:
404 Not Found. Description: The origin server did not find a current representation for the target resource or is not willing to disclose that one exists. Message: /LOGIN_RACMET_UI5_DynamicWebProject/LoginServlet
I need that the frontend is developed in SAPUI5, so I can't use JSP, PHP, etc.
The project is structured like this
When i do the call this is the result

I resolve it. It's wrong the url
$.post("LOGIN_RACMET_UI5_DynamicWebProject/LoginServlet", request, function() {
alert("Ciao");
});
This is right

Related

403 (Forbidden) response from SignalR Hub using ASP.NET hosting on IIS server

I'm hosting a SignalR Hub on Windows Server 2012 with IIS as an ASP.NET Web application that I've tested successfully on my local machine. But when I publish and try to connect from a Angular application the server responds with 403 Forbidden on the /negotiate request. The Angular application is located on a different domain then the Hub server.
I've read that this is caused by a CORS issue, but I've tried every solution I can find without any change. Can it be a IIS server issue or have I missed something in my code?
The route being called is https://example.com/signalr/negotiate
SignalR Server:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true,
EnableDetailedErrors = true
};
map.RunSignalR(hubConfiguration);
});
}
}
// Hub that handles Online user list
public class OnlineHub : Hub
{
private static List<AppUserDto> _usersOnline = new List<AppUserDto>();
public OnlineHub()
{
// Automapper Setup
MappingConfig.Init();
}
public override Task OnConnected()
{
var user = GetUser();
_usersOnline.Add(user);
Clients.All.listUpdated(_usersOnline);
return base.OnConnected();
}
public override Task OnReconnected()
{
var user = GetUser();
// Add user to list of online users if it doesn't exist
if (!_usersOnline.Any(u => u.Email == user.Email))
{
_usersOnline.Add(user);
Clients.All.listUpdated(_usersOnline);
}
return base.OnReconnected();
}
public override Task OnDisconnected(bool stopCalled)
{
var user = GetUser();
if (!_usersOnline.Any(u => u.Email == user.Email))
{
// Remove user from list of online users
_usersOnline.Remove(user);
Clients.All.listUpdated(_usersOnline);
}
return base.OnDisconnected(stopCalled);
}
private AppUserDto GetUser()
{
using (var db = new EntityDbContext())
{
// Get connected AppUserDto
var user = db.AppUsers.FirstOrDefault(u => u.UserName == Context.User.Identity.Name);
// Add user to list of online users
if (user != null)
{
return Mapper.Map<AppUserDto>(user);
}
return null;
}
}
}
Angular Application SignalR Service
import { AppSettings } from './../app.settings';
import { EventEmitter, Injectable } from '#angular/core';
declare const $: any;
#Injectable()
export class SignalRService {
// Declare the variables
private proxy: any;
private connection: any;
private authData: any;
// create the Event Emitter
public messageReceived: EventEmitter<any>;
public connectionEstablished: EventEmitter<Boolean>;
public connectionExists: Boolean;
constructor(private appSettings: AppSettings) {
// Setup
this.connectionEstablished = new EventEmitter<Boolean>();
this.messageReceived = new EventEmitter<any>();
this.connectionExists = false;
}
public initialize(proxyName: string): void {
this.connection = $.hubConnection(this.appSettings.SIGNALR_BASE_URL);
this.proxy = this.connection.createHubProxy(proxyName);
this.registerOnServerEvents();
this.startConnection();
}
private startConnection(): void {
this.connection.start({withCredentials: false})
.done((data: any) => {
console.log('SignalR Connected with: ' + data.transport.name);
this.connectionEstablished.emit(true);
this.connectionExists = true;
})
.fail((error: any) => {
console.log('SignalR could not connect: ' + error);
this.connectionEstablished.emit(false);
});
}
private registerOnServerEvents() {
this.proxy.on('listUpdated', (list: any) => {
console.log(list);
this.messageReceived.emit(list);
});
}
}
initialize(proxyName) gets called from a controller to start a connection to the Hub.
UPDATE
I've tried to rebuild the server and Hub using .NET Core 2.0, but when I test that on the IIS server I get:
"Failed to load https://signalr.example.com/online/negotiate: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://example.com' is therefore not allowed access."
So it's still a CORS issue even though I've setup everything just as multiple guides have done.
I've had issues in the past where the api path you are trying to hit is actually a virtual directory, and then IIS returns you a 403 because it thinks you are trying to view / access that directory instead of the webAPI route.
GET api/negotiate will 403 if you have the directory api/negotiate on your server.
This will be the case if you WebApiController is located in your project in a directory like:
/api/negotiate/NegotiateApiController.cs
You can resolve this very easily if that's the case by either changing the route or the directory name.
Note: This will come back as a 405 on some browsers.

SignalR methods in WebApi controller not called in specific setup

Well, I have a signalR hub:
public class ReportHub : Hub
{
private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<ReportHub>();
public void SendMessage(string text)
{
Clients.All.sendMessage(text);
}
public static void ServerSendMessage(string text)
{
hubContext.Clients.All.sendMessage(text);
}
}
Also I have the client code in js, on some view
report.client.sendMessage = message => {
alert('message from server: '+ message);
}
And I have webapi action, like this:
[HttpGet]
[Route("api/Report/test")]
public int GetTest()
{
ReportHub.ServerSendMessage("message");
return 42;
}
When I open the view with signalR-catching js code in one browser, and in another browser window requesting the webapi action, by typing http://../api/report/test - all working, and alert is appearing
But when I calling webapi action via postman, or any other rest client, no effect at all, report.client.sendMessage = message => {
alert('message from server: '+ message);
} - not working
Can anyone help?
ReportHub.ServerSendMessage("message");
It is wrong.
You should return ReportHubContext for the connection before pushing the data to clients;
[HttpGet]
[Route("api/Report/test")]
public int GetTest()
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ReportHub>();
hubContext.ServerSendMessage("message");
return 42;
}

How know the url for my web api?

I try to create an outlook add-in with a Web API.
So i have my Global class with the following code
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
}
I have my controller with the following code
[HttpGet()]
public DataResponse GetData()
{
return new DataResponse()
{
Status = "Success",
Message = "Hello World"
};
}
So I try to send a Get request to have my DataResponse. I try to call my API in JS in my Add-in. with this code
$.getJSON('api/GetData')
.done(function (data) {
showNotification("Success", "Good job");
}).fail(function (status) {
showNotification('Error', "Wrong request");
});
My problem is I go always in my fail function. I thinks it's because my url is wrong (but I'm not totaly sure). But I don't know how find automaticly the good url to call my API.
I try to change 'api/GetData' by 'http://localhost/api/GetData' or 127.0.0.1, same error.
I try to follow this sample https://dev.office.com/code-samples-detail/5784 but I don't know where I missing something.

Notify registered clients using Websockets with AngularJS (angular-websocket-service) and Spring Boot

I am new in AngularJS as well as FullStack development. The architecture of my current app is already set up and should not change preferably (for security reasons). So far, I can emit messages to the server using angular-websocket-service. Here is the code snippet of the service from the front-end:
proxiMiamApp.service('WebSocketService', function ($websocket) {
var wsEndpoint = {};
this.openWsEndpoint = function () {
wsEndpoint = $websocket.connect("ws://localhost:9000/proximiamHandler");
console.log(wsEndpoint);
return wsEndpoint;
}
this.sendMessage = function(){
if($.isEmptyObject(this.wsEndpoint)){
this.openWsEndpoint();
}
eventUser = {
idEvent : '1',
idUser : '49'
};
wsEndpoint.register('/eventUser', function(){
console.log('Register OK!');
});
console.log('Ready!');
wsEndpoint.emit('/eventUser',eventUser);
}});
As for the back-end, I am using an implementation of the WebSocketHandler interface:
#Controller
public class ProximiamHandler implements WebSocketHandler {
#Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
System.out.println("afterConntectionEstablished called");
}
#Override
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
System.out.println("handleMessage called");
// My code here...
}
#Override
public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
System.out.println("handleTransportError called");
}
#Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
System.out.println("afterConnectionClosed called");
}
#Override
public boolean supportsPartialMessages() {
return true;
}}
The Implementation of the WebSocketHandler is called via Spring WebSocketConfigurer
#Configuration
#EnableWebSocket
#Controller
public class WebSocketConfig implements WebSocketConfigurer {
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/proximiamHandler").setAllowedOrigins("*");
}
#Bean
public WebSocketHandler myHandler() {
return new ProximiamHandler();
}}
My questions are:
Can I notify subscribed clients using this architecture?
If yes, how can I do it?
Is there a way to return something to subscribed clients from the server? (an Object or a String for instance)
Thanks in advance for your help
Can I notify subscribed clients using this architecture?
=> Yes.
If yes, how can I do it?
=> Based on the Spring web socket APIs, you have to retain the ' WebSocketSession' passed to you via "afterConnectionEstablished" callback.
Use the sendMessage() API of Web socket session to send notifications to client.
Is there a way to return something to subscribed clients from the server? (an Object or a String for instance)
=> You can format your data in either JSON or XML & wrap it using "WebSocketMessage" and pass it to client.
I never worked on spring, however, I am answering this based on my knowledge on web socket. See if it helps.

spring boot / spring security is ignoring /login call from javascript

I am using Spring-Boot 1.1.7, with spring security, html (no thyme-leaf) and javascript. I am unable to get my login to work correctly when I use javascript to submit my login. When I use html with a form, spring-security picks up the requests, authenticates and proceeds happily. But with Javascript, I get a 302 redirect and no authentication.
Here is my configuration:
#ComponentScan
#EnableAutoConfiguration
#EnableGlobalMethodSecurity(securedEnabled = true)
public class MyApplication {
public static void main(String[] args) {
ApplicationContext edm = SpringApplication.run( MyApplication.class, args );
}
}
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsService customUserDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/menu").permitAll()
.antMatchers("/error").permitAll()
.antMatchers("/resources/**").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/fonts/**").permitAll()
.antMatchers("/libs/**").permitAll();
http
.formLogin().failureUrl("/login?error")
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/")
.permitAll();
http
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired")
.maxSessionsPreventsLogin(true)
.and()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/");
http
.authorizeRequests().anyRequest().authenticated();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = new BCryptPasswordEncoder();
auth.userDetailsService( customUserDetailsService ).passwordEncoder( encoder );
}
#Override
public void configure(WebSecurity security){
security.ignoring().antMatchers("/css/**","/fonts/**","/libs/**");
}
}
And I have my own UserDetailsService
#Component
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserService userService;
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
User user = userService.findByUsername( userName );
if ( user == null ) {
throw new UsernameNotFoundException( "UserName " + userName + " not found" );
}
return user;
}
}
And finally, here is the javascript that submits the post:
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$("#login").click(function(){
username=$("#username").val();
password=$("#password").val();
$.ajax({
type: "POST",
url: "/login",
beforeSend: function(xhr){
xhr.setRequestHeader(header, token);
},
data: "username="+username+"&password="+password,
success: function(html){
alert("logged in");
}
});
return false;
});
If I make this call from the url /login, I get the spring provided login form and all works perfectly. but I have a need to use javascript so I am wondering if there is something different I need to do to tell spring to look for it?
Here is the answer/solution that worked for me. Based on this article (http://patrickgrimard.com/2014/01/03/spring-security-csrf-protection-in-a-backbone-single-page-app/), adding a CSRFTokenGeneratorFilter extends OncePerRequestFilter and wiring it up to my security config, allowed my javascript provided parameters to be used.
public final class CSRFTokenGeneratorFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
CsrfToken token = (CsrfToken) request.getAttribute("_csrf");
response.setHeader("X-CSRF-HEADER", token.getHeaderName());
response.setHeader("X-CSRF-PARAM", token.getParameterName());
response.setHeader("X-CSRF-TOKEN", token.getToken());
filterChain.doFilter(request, response);
}
}
with wiring as:
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsService customUserDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new CSRFTokenGeneratorFilter(), CsrfFilter.class)
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
..}
}
I am not sure why the filter is needed, but I guess spring-boot/security doesn't use that as a default.
302 probably means your request either has invalid credentials or you are hitting filter protected area of the app. Are you sure that /login is the url spring filter listens to? I can't see where you set your request path for spring to listen to.. The default if I recall correctly is /j_spring_security_check with j_username and j_password.
Try to override login processing url.
Taking config from our prod as an example:
http
.formLogin()
.loginProcessingUrl("/app/authentication")
.successHandler(ajaxAuthenticationSuccessHandler)
.failureHandler(ajaxAuthenticationFailureHandler)
.usernameParameter("j_username")
.passwordParameter("j_password")
.permitAll()
Hope this helps.

Categories

Resources