xdoo / vaadin-demo

demo using vaadin with spring boot.
4 stars 2 forks source link

Security im Service einbauen #15

Closed xdoo closed 9 years ago

xdoo commented 9 years ago

In den Service muss security eingebaut werden. Die Struktur sollte hierbie sein, dass es für jede Operation, die über REST zur Verfügung gestellt eine (eindeutige und individuelle) Permission gibt. Diese Permissions werden zu Rollen zusammen gefasst, die rollen können dann Usern zu geordnet werden.

Artikel: http://www.baeldung.com/2011/11/20/basic-and-digest-authentication-for-a-restful-service-with-spring-security-3-1/ http://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#appendix-schema http://www.mkyong.com/spring-security/spring-security-form-login-using-database/

xdoo commented 9 years ago

Bitte die Security über standard Spring Security abbilden. Da sollte ungefähr folgende Tabellenstruktur dabei heraus kommen (auf die dann die Repositories, die du ja schon hast gelegt werden können):

--drop tables
drop table ACCOUNTS if exists;
drop table USERS if exists;
drop table USERS_AUTHORITYS if exists;
drop table AUTHORITYS if exists;
drop table AUTHORITYS_PERMISSIONS if exists;
drop table PERMISSIONS if exists;
drop table COMPANYBASEINFOS if exists;

-- Accounts table
create table ACCOUNTS (
  ID bigint generated by default as identity, 
  CREATED_BY varchar(255), 
  CREATED_DATE timestamp, 
  LAST_MOD_BY varchar(255), 
  LAST_MOD_DATE timestamp, 
  OID varchar(30) not null,
  primary key (ID));

-- Users table
create table USERS (
  ID bigint generated by default as identity, 
  CREATED_BY varchar(255), 
  CREATED_DATE timestamp, 
  LAST_MOD_BY varchar(255), 
  LAST_MOD_DATE timestamp, 
  OID varchar(30) not null,
  ACCOUNT_OID varchar(30) not null, 
  USER_USERNAME varchar(255),
  USER_PASSWORD varchar(255),
  USER_ENABLED boolean,
  USER_FORENNAME varchar(255),
  USER_SURENAME varchar(255),
  USER_BIRTHDATE timestamp,
  USER_EMAIL varchar(255),
  ACCOUNT_ID bigint,
  primary key (ID));

-- Authoritys table
create table AUTHORITYS (
  ID bigint generated by default as identity, 
  CREATED_BY varchar(255), 
  CREATED_DATE timestamp, 
  LAST_MOD_BY varchar(255), 
  LAST_MOD_DATE timestamp, 
  OID varchar(30) not null,
  AUTH_AUTHORITY varchar(255),
  primary key (ID));

-- Permissions table
create table PERMISSIONS (
  ID bigint generated by default as identity, 
  CREATED_BY varchar(255), 
  CREATED_DATE timestamp, 
  LAST_MOD_BY varchar(255), 
  LAST_MOD_DATE timestamp, 
  OID varchar(30) not null,
  PERM_PERMISSION varchar(255),
  primary key (ID));

-- CompanyBaseInfos table
create table COMPANYBASEINFOS (
  ID bigint generated by default as identity, 
  CREATED_BY varchar(255), 
  CREATED_DATE timestamp, 
  LAST_MOD_BY varchar(255), 
  LAST_MOD_DATE timestamp, 
  OID varchar(30) not null,
  ACCOUNT_OID varchar(30) not null, 
  COMP_NAME varchar(255),
  COMP_ADRESS varchar(255),
  primary key (ID));

-- join table for USERS and AUTHORITYS
create table USERS_AUTHORITYS (
  USER_ID bigint not null,
  AUTHORITY_ID bigint not null);

-- join table for AUTHORITYS and PERMISSIONS
create table AUTHORITYS_PERMISSIONS (
  AUTHORITY_ID bigint not null,
  PERMISSION_ID bigint not null);

-- unique constraints
alter table ACCOUNTS add constraint UK_OID_ON_ACCOUNTS unique (OID);
alter table USERS add constraint UK_OID_ON_USERS unique (OID);
alter table USERS add constraint UK_USER_USERNAME_ON_USERS unique (USER_USERNAME);
alter table AUTHORITYS add constraint UK_OID_ON_AUTHORITYS unique (OID);
alter table PERMISSIONS add constraint UK_OID_ON_PERMISSIONS unique (OID);
alter table COMPANYBASEINFOS add constraint UK_OID_ON_COMPANYBASEINFOS unique (OID);

-- foreingn key constraints
alter table USERS add constraint FK_USERS_TO_ACCOUNTS foreign key (ACCOUNT_ID) references ACCOUNTS;
alter table USERS_AUTHORITYS add constraint FK_USERS_AUTHORITYS_TO_AUTHORITYS foreign key (AUTHORITY_ID) references AUTHORITYS;
alter table AUTHORITYS_PERMISSIONS add constraint FK_AUTHORITYS_PERMISSIONS_TO_PERMISSIONS foreign key (PERMISSION_ID) references PERMISSIONS;

-- index constraints
create index IDX_ACCOUNTS_OID on ACCOUNTS (OID);
create index IDX_USERS_OID on USERS (OID);
create index IDX_USERS_ACCOUNT_OID on USERS (ACCOUNT_OID);
create index IDX_USERS_USER_FORENNAME on USERS (USER_FORENNAME);
create index IDX_USERS_USER_SURENAME on USERS (USER_SURENAME);
create index IDX_USERS_USER_BIRTHDATE on USERS (USER_BIRTHDATE);
create index IDX_AUTHORITYS_OID on AUTHORITYS (OID);
create index IDX_PERMISSIONS_OID on PERMISSIONS (OID);
create index IDX_COMPANYBASEINFOS_OID on COMPANYBASEINFOS (OID);
create index IDX_COMPANYBASEINFOS_ACCOUNT_OID on COMPANYBASEINFOS (ACCOUNT_OID);
create index IDX_COMPANYBASEINFOS_COMP_NAME on COMPANYBASEINFOS (COMP_NAME);
create index IDX_COMPANYBASEINFOS_COMP_ADRESS on COMPANYBASEINFOS (COMP_ADRESS);

In die Application.java würde dann etwa dieser Code kommen:

//    Security
    @Bean
    public ApplicationSecurity applicationSecurity() {
        LOG.info("creating application security...");
        return new ApplicationSecurity();
    }

    @Bean
    public AuthenticationManagerConfiguration authenticationSecurity() {
        return new AuthenticationManagerConfiguration();
    }

    @Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
             http
                .formLogin()
//                .loginPage("/app/pages/login.html")
                .and().logout().and().authorizeRequests()
                .antMatchers("/index.html", "/**/login.html", "/").permitAll().anyRequest()
                .authenticated()
                .and()       
                .csrf().csrfTokenRepository(csrfTokenRepository()).and()
                .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
        }

        private Filter csrfHeaderFilter() {
            return new OncePerRequestFilter() {
                @Override
                protected void doFilterInternal(HttpServletRequest request,
                        HttpServletResponse response, FilterChain filterChain)
                        throws ServletException, IOException {
                    CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
                            .getName());
                    if (csrf != null) {
                        Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                        String token = csrf.getToken();
                        if (cookie == null || token != null
                                && !token.equals(cookie.getValue())) {
                            cookie = new Cookie("XSRF-TOKEN", token);
                            cookie.setPath("/");
                            response.addCookie(cookie);
                        }
                    }
                    filterChain.doFilter(request, response);
                }
            };
        }

        private CsrfTokenRepository csrfTokenRepository() {
            HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
            repository.setHeaderName("X-XSRF-TOKEN");
            return repository;
        }
    }

    @Order(Ordered.HIGHEST_PRECEDENCE + 10)
    protected static class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter {

        @Autowired
        private DataSource dataSource;

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            auth
                    .jdbcAuthentication()
                    .passwordEncoder(new BCryptPasswordEncoder())
                    .dataSource(dataSource)
                    .usersByUsernameQuery("select USER_USERNAME, USER_PASSWORD, USER_ENABLED from USERS where USER_USERNAME=?")
                    .authoritiesByUsernameQuery("SELECT USERS.USER_USERNAME, AUTHORITYS.AUTH_AUTHORITY FROM USERS_AUTHORITYS JOIN USERS on USERS_AUTHORITYS.USER_ID = USERS.ID JOIN AUTHORITYS on USERS_AUTHORITYS.AUTHORITY_ID = AUTHORITYS.ID WHERE USERS.USER_USERNAME=?")
                    ;
        }
    }
xdoo commented 9 years ago

Um den CRSF Header zu realisieren brauchst du dann noch den entsprechenden Filter (Klasse CrsfHeaderFilter.java):

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils;

/**
 *
 * @author chris
 */
public class CsrfHeaderFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
                .getName());
        if (csrf != null) {
            Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
            String token = csrf.getToken();
            if (cookie == null || token != null && !token.equals(cookie.getValue())) {
                cookie = new Cookie("XSRF-TOKEN", token);
                cookie.setPath("/");
                response.addCookie(cookie);
            }
        }
        filterChain.doFilter(request, response);
    }
}

Im ersten Schritt kannst du aber die CRSF Sachen ausbauen, wenn das zuviele Probleme bereitet.

xdoo commented 9 years ago

Bitte eine Security REST API einbauen. Schau dir dazu mal die

xdoo commented 9 years ago

Sercurity Rest Schnittstelle #17

xdoo commented 9 years ago

Ich habe einige Kommentare zu deinem letzten Commit abgegeben (siehe oben). Wenn du Diskussionsbedarf siehst, dann einfach hier in den Kommentaren :)

xdoo commented 9 years ago

Aus meiner Sicht ist das implementiert und auch getestet. Wenn du das auch so siehst, dann würde ich dieses issue schließen.