Questions Spring Boot Web App -> Android

Asked

Viewed 595 times

2

A few weeks ago I finished the project of a web system that makes basic Ruds, I used Java, Maven, Spring Boot, Hibernate, Bootstrap + Thymeleaf pro frontend, etc... And I deployed to Heroku using the Postgresql database

Now I’m starting to develop for Android and want to create an app with a login screen and a Dashboard, I’m still working on the layout. The question is: For android is not at all recommended, by what I read, access an external database directly. That is, the ideal is to create an API that bridges with the database. So, I’ll have to rewrite my entire application or I can simply implement new Restful controllers or modify my controllers for my Android app to access the data?

NOTE: In my app I want the user to authenticate, but in my web app I didn’t use any framework for authentication, like Stormpath. Will I need to change that? Because the idea is to use the system both in the browser and by the application.

I will leave below a code snippet of one of the Controller:

@RequestMapping(value = "/sac/registration", method = RequestMethod.POST)
public ModelAndView createNewUser(@Valid User newUser, BindingResult bindingResult, String password, String role, RedirectAttributes attributes) {
    ModelAndView modelAndView = new ModelAndView();

    // Checks if already exists a user with the provided email, to avoid duplicity.
    User userExists = userService.findUserByEmail(newUser.getEmail());

    // Search for the authenticated user
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    User userAuthenticated = userService.findUserByEmail(auth.getName());

    if (userExists != null && password.length() < 5 && bindingResult.hasErrors()) {
        bindingResult
                    .rejectValue("email", "error.user",
                            "Já existe usuário com este e-mail!");
        return registration(newUser);
    }else
        if (password.length() < 5 || bindingResult.hasErrors()) {
            return registration(newUser);
        }else
            if (userExists != null || bindingResult.hasErrors()) {
                bindingResult
                            .rejectValue("email", "error.user",
                                    "Já existe usuário com este e-mail!");              
                return registration(newUser);               
            } else {
                userService.saveUser(newUser, role);
                attributes.addFlashAttribute("successMessage", "Usuário cadastrado com sucesso!");
                modelAndView.addObject("role", roleService.findAllRoles());
                modelAndView.addObject("userName", userAuthenticated.getName() + " (" + userAuthenticated.getEmail() + ")");
                modelAndView.setViewName("redirect:/sac/registration");         
            }

    return modelAndView;

}

EDIT:

Today system authentication is done using Spring Security. Will it be necessary to change all form of system authentication for my Android App to access? Below I will leave the codes used for authentication:

Securityconfiguration.java

@Configuration @Enablewebsecurity public class Securityconfiguration extends Websecurityconfigureradapter {

/*
 * @author: Cisino Junior
 */

@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    auth
        .userDetailsService(userDetailsService)
        .passwordEncoder(bCryptPasswordEncoder);

}

@Override
protected void configure(HttpSecurity http) throws Exception {      
    http.
        authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/login").permitAll()
            .antMatchers("/access-denied").permitAll()
            .antMatchers("/sac/registration").hasAuthority("ADMIN")
            .antMatchers("/sac/consultarUsuarios").hasAuthority("ADMIN")
            .antMatchers("/sac/index").hasAnyAuthority("ADMIN", "SUPPORT")
            .antMatchers("/sac/**").hasAnyAuthority("ADMIN", "SUPPORT").anyRequest()                
            //.authenticated().and().csrf().disable().formLogin()
            .authenticated().and().formLogin()
            .loginPage("/login").failureUrl("/login?error=true")
            .defaultSuccessUrl("/sac/index")
            .usernameParameter("email")
            .passwordParameter("password")
            .and().logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/login").and().exceptionHandling()
            .accessDeniedPage("/access-denied");
}

@Override
public void configure(WebSecurity web) throws Exception {
    web
       .ignoring()
       .antMatchers("/resources/**","/static/**", "/css/**", "/js/**", "/font-awesome/**", "/fonts/**");
} }

Userserviceimpl.java

@Service("userService")

@Transactional public class Userserviceimpl Implements Userservice, Userdetailsservice {
/* * @Author: Cisino Junior */

@Autowired
private UsuarioRepository userRepository;

@Autowired
private RoleRepository roleRepository;

@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;


@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
    User user = userRepository.findByEmail(email);
    List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
    return buildUserForAuthentication(user, authorities);
}

private List<GrantedAuthority> getUserAuthority(Set<Role> userRoles) {
    Set<GrantedAuthority> roles = new HashSet<GrantedAuthority>();
    for (Role role : userRoles) {
        roles.add(new SimpleGrantedAuthority(role.getRole()));
    }

    List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>(roles);
    return grantedAuthorities;
}

private UserDetails buildUserForAuthentication(User user, List<GrantedAuthority> authorities) {
    return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), user.getActive(), true, true, true, authorities);
}}
  • Hello, looking for the same solution I found some references. Follow the links: .. http://andreybleme.com/2017-04-01/autenticaca-com-jwt-no-spring-boot ... https://www.youtube.com/playlist?list=PL62G310vn6nF3gssjqfCKLpTK2sZJ_a_1 .... https://www.youtube.com/watch?v=Nwhp_C_BG6c

1 answer

2


The ideal would be to have an api that both your front and mobile app could consume... But since it’s all written down, you can reuse the other layers (service, Repository, etc) you’ve already written, but you need to implement the endpoints your mobile app will consume.

You are already using a framework that takes care of authentication, from a searched in Oauth or JWT with Spring Boot.

  • I understand, so I can create the controllers pro mobile app consume, show!!! But the issue of authentication is a bit confusing, I did the authentication using the Userdetailsservice interface and use Thymeleaf on the front end to hide elements depending on the type of user, example: <li sec:Authorize="hasAuthority('ADMIN')" >

  • I’m using Spring Security, it’s not enough for my app to access safely? Sorry to bother you, but this is a little confusing for me yet.

  • 1

    I think the main point that’s confusing you is client-server architecture. Keep in mind that both your mobile app and browser are clients and communication with your backend(server) is through HTTP requests. On your front you can use tags like sec:Authorize because of the view engine (Thymeleaf) that renders html, already on mobile, if it’s a native app, it won’t be possible. Now if your app is a webview, you don’t need to change anything...

  • I don’t think I expressed myself correctly. My biggest doubt is in the mobile app authentication, which will be native(In java anyway, because at the moment I do not have time to dedicate myself to Kotlin)... So I have to change the way the system authenticates, is that it? Because the way it is today a native mobile app will not be able to access? I will edit my question and leave excerpts from the system config classes for you to see how it is being done. Again, sorry to bother you and thank you for your help Tom!!!

  • Exactly, Oauth or JWT is usually used for mobile authentication. The authentication process is different, you will not have an open session for each logged-in user, you will have an authentication token that will be sent by the mobile app in all requests on protected endpoints. Do you really need a native app? Can’t make your layout responsive and use a webview? Otherwise, I think it’s a good idea to rewrite your application already thinking about a Rest api being consumed by different clients (browser, mobile and etc).

  • So the layout is fully responsive and works perfectly on smartphones. I want to make the app native because I am studying Android and I would like to use this situation as an example for study and was with this doubt regarding authentication. The ideal would be to actually rewrite the application, but that would take a lot of time and I need to focus more on Android now. I believe that if I change the authentication and create the Rest controllers it will be enough for the native app to access, right? Even if it is not ideal rs

  • It will be very confusing, but it should work...try to implement, start with a user registration, then authentication and etc.

  • I’ll try! Thanks for your help Tom!!!

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.