Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support spring security auth #732

Merged
merged 1 commit into from
Sep 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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