Commit 9258ec85 by chenzx

tb-sso单点登录流程

parent de29735b
......@@ -79,6 +79,12 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
<!-- CXF webservice -->
<dependency>
......
......@@ -2,8 +2,10 @@ package com.keymobile.proxy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class LoginApplication {
public static void main(String[] args) {
......
......@@ -7,6 +7,7 @@ public class Constants {
public static final String Session_UserDName = "userDName";
public static final String Session_Roles = "roles";
public static final String Session_Lang = "lang";
public static final String ROLE_PREFIX = "ROLE_";
}
package com.keymobile.proxy.api;
import com.keymobile.proxy.util.Des;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Properties;
@RestController
@RequestMapping("/sso")
public class SSOCtrl {
private Logger logger = LoggerFactory.getLogger(SSOCtrl.class);
@RequestMapping(value = "/login", method = {RequestMethod.POST ,RequestMethod.GET })
@ResponseBody
public void login(HttpServletRequest request, HttpServletResponse response,
@RequestParam(name = "portal_actionURL") String portal_actionURL,
@RequestParam(name = "portal_username") String portal_username,
@RequestParam(name = "portal_password") String portal_password,
@RequestParam(name = "CallBack") String callBack,
@RequestParam(name = "key") String key) {
Des des = new Des();
String pwd = des.strDec(portal_password, key);
logger.info("sso login param->userName:"+portal_username+" pwd:"+pwd);
String str = "";
if(authenticate(portal_username,pwd)){
str = callBack+"({'query':{'results':{'postresult':'portal_ssologin_succeed'}}});";
}else{
str = callBack+"({'query':{'results':{'postresult':'portal_ssologin_fali'}}});";
}
try {
PrintWriter out = response.getWriter();
out.println(str);
out.flush();
out.close();
}catch (Exception e){
logger.info("PrintWriter Exception:"+e.getLocalizedMessage());
e.printStackTrace();
}
}
/**
* 验证用户登录
*
* @param userName
* String 用户名格式为 username或者username@hntobacco.com
湖南内网的domain必须是@hntobacco.com,不是hnyc.com
* @param password
* String
* @return boolean
*/
public boolean authenticate(String userName, String password) {
if (password != null && !"".equals(password.trim())) {
DirContext ctx1;
try {
String domain = "@hntobacco.com";
Properties ldapEnv = new Properties();
ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
ldapEnv.put(Context.PROVIDER_URL, "ldap://hntobacco.com:389");//服务器必须配置DNS,否则无法解析hntobacc.com
ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
String user = userName.indexOf(domain) > 0 ? userName : userName
+ domain;
ldapEnv.put(Context.SECURITY_PRINCIPAL, user);
ldapEnv.put(Context.SECURITY_CREDENTIALS, password);
ctx1 = new InitialDirContext(ldapEnv);
ctx1.close();
logger.info("登录验证成功!");
return true;
} catch (AuthenticationException e) {
logger.info("登录失败!"+e.getLocalizedMessage());
e.printStackTrace();
return false;
} catch (NamingException e) {
logger.info("登录失败!"+e.getLocalizedMessage());
e.printStackTrace();
return false;
}
} else {
logger.info("登录验证失败!");
return false;
}
}
}
package com.keymobile.proxy.conf;
import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignClientConfig {
@Value("${security.authUser}")
private String authUser;
@Value("${security.authPwd}")
private String authPwd;
@Bean
public BasicAuthRequestInterceptor getBasicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor(authUser, authPwd);
}
}
......@@ -27,7 +27,13 @@ public class RESTAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuc
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
clearAuthenticationAttributes(request);
String returnStatus = "ok";
String data = (String) request.getSession().getAttribute("ssoLogin");
System.out.println("come onAuthenticationSuccess here");
if(null == data){
System.out.println("getAttribute('ssoLogin') is null");
data = "ok";
}
String returnStatus = data;
//check if allow root login
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
......@@ -35,6 +41,9 @@ public class RESTAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuc
if (userNameWithIdAttached.split(":")[0].equalsIgnoreCase("root")
&& !rootAllowLogin)
returnStatus = "root not allow login";
//response.sendRedirect("/sso/go");
PrintWriter writer = response.getWriter();
writer.write(returnStatus);
writer.flush();
......
package com.keymobile.proxy.conf;
import com.keymobile.proxy.api.Constants;
import com.keymobile.proxy.model.Author;
import com.keymobile.proxy.model.Domain;
import com.keymobile.proxy.model.Role;
import com.keymobile.proxy.service.AuthService;
import com.keymobile.proxy.util.Des;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
private static final String usersQuery = "select concat(user_name, ':', user_id, ':', user_dname), password, true \n" +
"from auth_user where user_name = ?";
private static final String rolesQuery = "select t1.user_name, concat(concat('ROLE_', t1.author_name), ':', GROUP_CONCAT(COALESCE(t2.domain_id, '*'))) as role_name \n" +
......@@ -39,6 +68,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
private RESTLogoutSuccessHandler logoutSuccessHandler;
@Autowired
private AuthService authService;
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().usersByUsernameQuery(usersQuery).authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource).passwordEncoder(NoOpPasswordEncoder.getInstance());
......@@ -58,4 +90,111 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
http.sessionManagement().maximumSessions(1).expiredUrl("/login");
}
}
@Bean
public AbstractAuthenticationProcessingFilter authenticationFilter() throws Exception {
AbstractAuthenticationProcessingFilter authenticationFilter = new AbstractAuthenticationProcessingFilter("/ssoauth") {
@Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
String portal_actionURL = httpServletRequest.getParameter("portal_actionURL");
String username = httpServletRequest.getParameter("portal_username");
String portal_password = httpServletRequest.getParameter("portal_password");
String CallBack = httpServletRequest.getParameter("CallBack");
String key = httpServletRequest.getParameter("key");
if(null == username || null == portal_password ||
null == CallBack ||null == key){
httpServletResponse.sendError(500,"sso login url missing request param");
return null;
}
Des des = new Des();
String pwd = des.strDec(portal_password, key);
logger.info("sso login param->userName:"+username+" pwd:"+pwd);
if(!authenticate(username,pwd)){
httpServletResponse.sendError(500,"({'query':{'results':{'postresult':'portal_ssologin_fali'}}});");
return null;
}
httpServletRequest.getSession().setAttribute("ssoLogin","({'query':{'results':{'postresult':'portal_ssologin_succeed'}}});");
com.keymobile.proxy.model.User u = authService.getUserByName(username);
if (u == null) {
u = new com.keymobile.proxy.model.User();
u.setName(username);
u.setPassword("37fa265330ad83eaa879efb1e2db6380896cf639");//pwd
u.setDName(username);
u = authService.addUser(new Long[] { (long) 4 }, new Long[] {}, u);
this.logger.info("单点登录新增用户:"+authService);
}
List<GrantedAuthority> authorities = new ArrayList<>();
String userName = u.getName() + ":" + u.getId() + ":" + u.getDName();
String userDomainFilterStr = "*";
List<String> userDomainList = new ArrayList<>();
List<Domain> domainsOfUser = authService.getDomainsOfUser(u.getId());
domainsOfUser.forEach(d -> userDomainList.add(d.getDomainId().toString()));
if (userDomainList.size() > 0) {
userDomainFilterStr = String.join(",", userDomainList);
}
List<Role> rolesOfUser = authService.getRolesOfUser(u.getId());
for (Role role : rolesOfUser) {
List<Author> authors = authService.getAuthorsOfRole(role.getRoleId());
for (Author author: authors) {
GrantedAuthority authorityInfo = new SimpleGrantedAuthority(Constants.ROLE_PREFIX + author.getAuthorName() + ":" + userDomainFilterStr);
authorities.add(authorityInfo);
}
}
Authentication auth = new UsernamePasswordAuthenticationToken(new User(userName, "whatever", authorities), null, authorities);
return auth;
}
};
authenticationFilter.setAuthenticationManager(authenticationManager());
authenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
return authenticationFilter;
}
/**
* 验证用户登录
*
* @param userName
* String 用户名格式为 username或者username@hntobacco.com
湖南内网的domain必须是@hntobacco.com,不是hnyc.com
* @param password
* String
* @return boolean
*/
public boolean authenticate(String userName, String password) {
if (password != null && !"".equals(password.trim())) {
DirContext ctx1;
try {
String domain = "@hntobacco.com";
Properties ldapEnv = new Properties();
ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
ldapEnv.put(Context.PROVIDER_URL, "ldap://hntobacco.com:389");//服务器必须配置DNS,否则无法解析hntobacc.com
ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
String user = userName.indexOf(domain) > 0 ? userName : userName
+ domain;
ldapEnv.put(Context.SECURITY_PRINCIPAL, user);
ldapEnv.put(Context.SECURITY_CREDENTIALS, password);
ctx1 = new InitialDirContext(ldapEnv);
ctx1.close();
logger.info("登录验证成功!");
return true;
} catch (javax.naming.AuthenticationException e) {
logger.info("登录失败!"+e.getLocalizedMessage());
e.printStackTrace();
return false;
} catch (NamingException e) {
logger.info("登录失败!"+e.getLocalizedMessage());
e.printStackTrace();
return false;
}
} else {
logger.info("登录验证失败!");
return false;
}
}
}
\ No newline at end of file
package com.keymobile.proxy.model;
public class Author {
private Long id;
private String name;
public Author() {}
public Long getAuthorId() {
return id;
}
public void setAuthorId(Long id) {
this.id = id;
}
public String getAuthorName() {
return name;
}
public void setAuthorName(String name) {
this.name = name;
}
}
package com.keymobile.proxy.model;
public class Domain {
private Long id;
private String name;
public Domain() {}
public Domain(String name) {
this.name = name;
}
public Long getDomainId() {
return id;
}
public void setDomainId(Long id) {
this.id = id;
}
public String getDomainName() {
return name;
}
public void setDomainName(String name) {
this.name = name;
}
}
package com.keymobile.proxy.model;
public class Role {
private Long id;
private String name;
private String dname;
public Role() {}
public Long getRoleId() {
return id;
}
public void setRoleId(Long id) {
this.id = id;
}
public String getRoleName() {
return name;
}
public void setRoleName(String name) {
this.name = name;
}
public String getRoleDName() {
return dname;
}
public void setRoleDName(String dname) {
this.dname = dname;
}
}
package com.keymobile.proxy.model;
import java.util.List;
public class User {
private Long id;
private String name;
private String dname;
private String password;
private List<Role> roles;
private List<Domain> domains;
public User() {}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDName() {
return dname;
}
public void setDName(String dname) {
this.dname = dname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
System.out.println(password);
this.password = password;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public List<Domain> getDomains() {
return domains;
}
public void setDomains(List<Domain> domains) {
this.domains = domains;
}
}
package com.keymobile.proxy.service;
import com.keymobile.proxy.model.Author;
import com.keymobile.proxy.model.Domain;
import com.keymobile.proxy.model.Role;
import com.keymobile.proxy.model.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@FeignClient(value = "authService")
public interface AuthService {
@RequestMapping(value = "/user")
User getUserByName(@RequestParam(value = "name") String name);
@PostMapping(value = "/users/{userId}")
User updateUser(@PathVariable(value = "userId") Long userId, @RequestBody User user);
@RequestMapping(value = "/users", method = RequestMethod.POST)
User addUser(@RequestParam(value = "roleIds", required = false) Long[] roleIds
, @RequestParam(value = "domainIds", required = false) Long[] domainIds, @RequestBody User user);
@RequestMapping(value = "/roles/{roleId}/authors", method = RequestMethod.GET)
List<Author> getAuthorsOfRole(@PathVariable(value = "roleId") Long roleId);
@RequestMapping(value = "/users/{userId}/roles", method = RequestMethod.GET)
List<Role> getRolesOfUser(@PathVariable(value = "userId") Long userId);
@RequestMapping(value = "/users/{userId}/domains", method = RequestMethod.GET)
List<Domain> getDomainsOfUser(@PathVariable(value = "userId") Long userId);
}
package com.keymobile.proxy.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@FeignClient(value = "portal")
public interface PortalService {
@RequestMapping(value = "/user/getStatus")
Integer getUserStatus(@RequestParam(value = "userId") String userId);
}
package com.keymobile.proxy.wss.impl;
import com.keymobile.proxy.service.PortalService;
import com.keymobile.proxy.wss.WebServerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.jws.WebService;
......@@ -14,6 +16,9 @@ public class WebServerServiceImpl implements WebServerService {
private Logger logger = LoggerFactory.getLogger(WebServerServiceImpl.class);
@Autowired
private PortalService portalService;
@Override
public String GetPermission(String userId) {
if(null == userId || "".equals(userId.trim())){
......@@ -21,6 +26,10 @@ public class WebServerServiceImpl implements WebServerService {
return "0";
}
logger.info("GetPermission传递userId:"+userId);
Integer status = portalService.getUserStatus(userId);
if(null == status ||status == 0){
return "0";
}
return "1";
}
}
......@@ -33,7 +33,7 @@ spring:
eureka:
client:
registerWithEureka: false
registerWithEureka: true
region: default
registryFetchIntervalSeconds: 5
serviceUrl:
......@@ -48,4 +48,9 @@ logging:
org.springframework.security: DEBUG
redirect-url:
system-management: http://192.168.0.216:8089/views/login.html
\ No newline at end of file
system-management: http://192.168.0.216:9090/center-home/view/index
security:
permit: false
authUser: root
authPwd: pwd
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment