Skip to content

Commit

Permalink
support spring security auth
Browse files Browse the repository at this point in the history
  • Loading branch information
lepdou committed Sep 5, 2017
1 parent 9721ba3 commit b1d0745
Show file tree
Hide file tree
Showing 28 changed files with 916 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ protected void refresh() {
this.source.put(key, value);

}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
auth.inMemoryAuthentication().withUser("user").password("").roles("USER").and()
.withUser("apollo").password("").roles("USER", "ADMIN");
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.ctrip.framework.apollo.common.config;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;

import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
import com.ctrip.framework.apollo.tracer.Tracer;

import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ public class PortalConfig extends RefreshableConfig {
private static final Type ORGANIZATION = new TypeToken<List<Organization>>() {
}.getType();


@Autowired
private PortalDBPropertySource portalDBPropertySource;


@Override
public List<RefreshablePropertySource> getRefreshablePropertySources() {
return Collections.singletonList(portalDBPropertySource);
Expand Down Expand Up @@ -102,7 +100,7 @@ public boolean isEmergencyPublishAllowed(Env env) {

String[] emergencyPublishSupportedEnvs = getArrayProperty("emergencyPublish.supported.envs", new String[0]);

for (String supportedEnv: emergencyPublishSupportedEnvs) {
for (String supportedEnv : emergencyPublishSupportedEnvs) {
if (Objects.equals(targetEnv, supportedEnv.toUpperCase().trim())) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ public class AppController {
@Autowired
private RolePermissionService rolePermissionService;


@RequestMapping(value = "", method = RequestMethod.GET)
public List<App> findApps(@RequestParam(value = "appIds", required = false) String appIds) {
if (StringUtils.isEmpty(appIds)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.ctrip.framework.apollo.portal.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
* @author lepdou 2017-08-30
*/
@Controller
public class SignInController {

@RequestMapping(value = "/signin", method = RequestMethod.GET)
public String login(@RequestParam(value = "error", required = false) String error,
@RequestParam(value = "logout", required = false) String logout) {
return "login.html";
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.ctrip.framework.apollo.portal.controller;

import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import com.ctrip.framework.apollo.portal.entity.bo.UserInfo;
import com.ctrip.framework.apollo.portal.spi.LogoutHandler;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import com.ctrip.framework.apollo.portal.entity.bo.UserInfo;
import com.ctrip.framework.apollo.portal.spi.UserService;
import com.ctrip.framework.apollo.portal.spi.springsecurity.SpringSecurityUserService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.User;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
Expand All @@ -29,6 +35,22 @@ public class UserInfoController {
@Autowired
private UserService userService;


@PreAuthorize(value = "@permissionValidator.isSuperAdmin()")
@RequestMapping(value = "/users", method = RequestMethod.POST)
public void createOrUpdateUser(@RequestBody User user) {
if (StringUtils.isContainEmpty(user.getUsername(), user.getPassword())) {
throw new BadRequestException("Username and password can not be empty.");
}

if (userService instanceof SpringSecurityUserService) {
((SpringSecurityUserService) userService).createOrUpdate(user);
} else {
throw new UnsupportedOperationException("Create or update user operation is unsupported");
}

}

@RequestMapping(value = "/user", method = RequestMethod.GET)
public UserInfo getCurrentUserName() {
return userInfoHolder.getUser();
Expand All @@ -50,4 +72,6 @@ public List<UserInfo> searchUsersByKeyword(@RequestParam(value = "keyword") Stri
public UserInfo getUserByUserId(@PathVariable String userId) {
return userService.findByUserId(userId);
}


}
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
package com.ctrip.framework.apollo.portal.entity.bo;

public class UserInfo {
public static final UserInfo DEFAULT_USER = new UserInfo("apollo");

private String userId;
private String name;
private String email;

public UserInfo() {

}

public UserInfo(String userId) {
this.userId = userId;
}

public String getUserId() {
return userId;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.ctrip.framework.apollo.portal.entity.po;

import com.ctrip.framework.apollo.portal.entity.bo.UserInfo;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

/**
* @author lepdou 2017-04-08
*/
@Entity
@Table(name = "users")
public class UserPO {

@Id
@GeneratedValue
@Column(name = "Id")
private long id;
@Column(name = "username", nullable = false)
private String username;
@Column(name = "password", nullable = false)
private String password;
@Column(name = "enabled", nullable = false)
private int enabled;

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public int getEnabled() {
return enabled;
}

public void setEnabled(int enabled) {
this.enabled = enabled;
}

public UserInfo toUserInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setName(this.getUsername());
userInfo.setUserId(this.getUsername());
userInfo.setEmail("[email protected]");
return userInfo;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.ctrip.framework.apollo.portal.repository;

import com.ctrip.framework.apollo.portal.entity.po.UserPO;

import org.springframework.data.repository.PagingAndSortingRepository;

import java.util.List;

/**
* @author lepdou 2017-04-08
*/
public interface UserRepository extends PagingAndSortingRepository<UserPO, Long> {

List<UserPO> findByUsernameLike(String username);

UserPO findByUsername(String username);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.ctrip.framework.apollo.portal.spi.configuration;

import com.google.common.collect.Maps;

import com.ctrip.framework.apollo.common.condition.ConditionalOnMissingProfile;
import com.ctrip.framework.apollo.portal.component.config.PortalConfig;
import com.ctrip.framework.apollo.portal.spi.LogoutHandler;
import com.ctrip.framework.apollo.portal.spi.SsoHeartbeatHandler;
Expand All @@ -13,14 +16,27 @@
import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultSsoHeartbeatHandler;
import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultUserInfoHolder;
import com.ctrip.framework.apollo.portal.spi.defaultimpl.DefaultUserService;
import com.google.common.collect.Maps;
import com.ctrip.framework.apollo.portal.spi.springsecurity.SpringSecurityUserInfoHolder;
import com.ctrip.framework.apollo.portal.spi.springsecurity.SpringSecurityUserService;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;

import javax.servlet.Filter;
import java.util.EventListener;
Expand Down Expand Up @@ -170,10 +186,89 @@ public SsoHeartbeatHandler ctripSsoHeartbeatHandler() {


/**
* spring.profiles.active != ctrip
* spring.profiles.active = auth
*/
@Configuration
@Profile({"!ctrip"})
@Profile("auth")
static class SpringSecurityAuthAutoConfiguration {

@Bean
@ConditionalOnMissingBean(SsoHeartbeatHandler.class)
public SsoHeartbeatHandler defaultSsoHeartbeatHandler() {
return new DefaultSsoHeartbeatHandler();
}

@Bean
@ConditionalOnMissingBean(UserInfoHolder.class)
public UserInfoHolder springSecurityUserInfoHolder() {
return new SpringSecurityUserInfoHolder();
}

@Bean
@ConditionalOnMissingBean(LogoutHandler.class)
public LogoutHandler logoutHandler() {
return new DefaultLogoutHandler();
}

@Bean
public JdbcUserDetailsManager jdbcUserDetailsManager(DataSource datasource) {
JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager();
userDetailsService.setDataSource(datasource);

return userDetailsService;
}

@Bean
@ConditionalOnMissingBean(UserService.class)
public UserService springSecurityUserService() {
return new SpringSecurityUserService();
}


@Order(99)
@Configuration
@Profile("auth")
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class SpringSecurityConfigurer extends WebSecurityConfigurerAdapter {

public static final String USER_ROLE = "user";

@Autowired
private DataSource datasource;


@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.headers().frameOptions().sameOrigin();
http.authorizeRequests()
.antMatchers("/openapi/*").permitAll()
.antMatchers("/*").hasAnyRole(USER_ROLE);
http.formLogin().loginPage("/signin").permitAll().failureUrl("/signin?#/error").and().httpBasic();
http.logout().invalidateHttpSession(true).clearAuthentication(true).logoutSuccessUrl("/signin?#/logout");
http.exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/signin"));
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, JdbcUserDetailsManager userDetailsService)
throws Exception {
PasswordEncoder encoder = new BCryptPasswordEncoder();

auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
auth.jdbcAuthentication().dataSource(datasource).usersByUsernameQuery(
"select username,password, enabled from users where username=?");
}

}

}

/**
* default profile
*/
@Configuration
@ConditionalOnMissingProfile({"ctrip", "auth"})
static class DefaultAuthAutoConfiguration {

@Bean
Expand All @@ -184,7 +279,7 @@ public SsoHeartbeatHandler defaultSsoHeartbeatHandler() {

@Bean
@ConditionalOnMissingBean(UserInfoHolder.class)
public DefaultUserInfoHolder notCtripUserInfoHolder() {
public DefaultUserInfoHolder defaultUserInfoHolder() {
return new DefaultUserInfoHolder();
}

Expand All @@ -199,8 +294,6 @@ public DefaultLogoutHandler logoutHandler() {
public UserService defaultUserService() {
return new DefaultUserService();
}

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@
import com.ctrip.framework.apollo.portal.entity.bo.UserInfo;
import com.ctrip.framework.apollo.portal.spi.UserService;

import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* @author Jason Song([email protected])
Expand Down
Loading

0 comments on commit b1d0745

Please sign in to comment.