package ru.codeinside.auth;
import com.google.common.collect.Sets;
import ru.codeinside.adm.AdminServiceProvider;
import ru.codeinside.adm.database.Employee;
import ru.codeinside.adm.database.Role;
import ru.codeinside.esia.AppData;
import ru.codeinside.esia.ConnectESIA;
import ru.codeinside.esia.ConnectESIAService;
import ru.codeinside.esia.DataRow;
import ru.codeinside.esia.Exception_Exception;
import ru.codeinside.esia.MessageConnectESIAData;
import ru.codeinside.esia.MessageType;
import ru.codeinside.esia.OrgExternalType;
import ru.codeinside.esia.Result;
import ru.codeinside.esia.ResultAppData;
import ru.codeinside.esia.ResultMessageDataType;
import ru.codeinside.esia.StatusType;
import ru.codeinside.esia.TypeCodeType;
import ru.codeinside.filter.AuthorizationFilter;
import ru.codeinside.gses.API;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Holder;
import javax.xml.ws.WebServiceException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
@WebServlet(urlPatterns = {"/authServlet"})
public class AuthServlet extends HttpServlet {
private Logger log = Logger.getLogger(AuthServlet.class.getName());
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String isEsiaAuth = req.getParameter("isEsiaAuth");
if ("on".equals(isEsiaAuth)) {
esiaAuthorization(req, resp);
} else {
standardAuthorization(req, resp);
}
}
private void standardAuthorization(HttpServletRequest req, HttpServletResponse resp) {
String login = req.getParameter("username");
String password = req.getParameter("password");
Employee employee = AdminServiceProvider.get().findEmployeeByLogin(login);
if (employee != null && employee.checkPassword(password)) {
setPrincipal(req, employee);
sendRedirect(resp, "/web-client/");
} else {
sendForward(req, resp, "/loginError.jsp", "loginError");
}
}
private void esiaAuthorization(HttpServletRequest req, HttpServletResponse resp) {
String snils = req.getParameter("snils");
String baseSnils = snils.replaceAll("\\D+", "");
String pass = req.getParameter("password");
Employee user = null;
try {
user = AdminServiceProvider.get().findEmployeeBySnils(baseSnils);
} catch (IllegalStateException e) {
log.severe(e.getMessage());
sendForward(req, resp, "/loginError.jsp", "notUniqueSnils");
}
try {
if (user != null && createEsiaRequest(snils, pass)) {
setPrincipal(req, user);
resp.setStatus(HttpServletResponse.SC_OK);
sendRedirect(resp, "/web-client/");
} else {
sendForward(req, resp, "/loginError.jsp", "snilsError");
}
} catch (Exception_Exception e) {
e.printStackTrace();
sendForward(req, resp, "/loginError.jsp", "esiaError");
} catch (MalformedURLException e) {
e.printStackTrace();
sendForward(req, resp, "/loginError.jsp", "esiaError");
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
sendForward(req, resp, "/loginError.jsp", "esiaError");
} catch (WebServiceException e) {
e.printStackTrace();
sendForward(req, resp, "/loginError.jsp", "esiaError");
}
}
private Boolean createEsiaRequest(String snils, String pass) throws Exception_Exception, MalformedURLException, DatatypeConfigurationException {
Holder<MessageType> message = getMessage();
MessageConnectESIAData messageData = getMessageData(snils, pass);
Holder<ResultMessageDataType> result = getResult();
String serviceAddress = AdminServiceProvider.get().getSystemProperty(API.ESIA_SERVICE_ADDRESS);
ConnectESIAService service = new ConnectESIAService();
ConnectESIA endpoint = service.getConnectESIAPort();
BindingProvider provider = (BindingProvider) endpoint;
Map<String, Object> requestContext = provider.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, serviceAddress);
endpoint.getConnectESIA(message, messageData, result);
return getEsiaRequestResult(result);
}
private Holder<MessageType> getMessage() throws DatatypeConfigurationException {
MessageType message = new MessageType();
OrgExternalType sender = new OrgExternalType();
sender.setCode("604101");
sender.setName("Автоматизированная информационная система ДОКА (Пензенской области)");
OrgExternalType recipient = new OrgExternalType();
recipient.setCode("OEP");
recipient.setName("OEP");
OrgExternalType originator = new OrgExternalType();
originator.setCode("604101");
originator.setName("Автоматизированная информационная система ДОКА (Пензенской области)");
message.setSender(sender);
message.setRecipient(recipient);
message.setOriginator(originator);
message.setTypeCode(TypeCodeType.GSRV);
message.setStatus(StatusType.REQUEST);
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(new Date());
XMLGregorianCalendar date = DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar);
message.setDate(date);
message.setExchangeType("2");
Holder<MessageType> messageHolder = new Holder<MessageType>();
messageHolder.value = message;
return messageHolder;
}
private MessageConnectESIAData getMessageData(String snils, String pass) {
MessageConnectESIAData messageData = new MessageConnectESIAData();
Result result = new Result();
List<DataRow> dataRows = result.getDataRow();
DataRow snilsData = new DataRow();
snilsData.setName("username");
snilsData.setValue(snils);
DataRow passData = new DataRow();
passData.setName("password");
passData.setValue(pass);
dataRows.add(snilsData);
dataRows.add(passData);
AppData appData = new AppData();
appData.setResult(result);
messageData.setAppData(appData);
return messageData;
}
private Holder<ResultMessageDataType> getResult() {
ResultMessageDataType resultType = new ResultMessageDataType();
ResultAppData resultAppData = new ResultAppData();
resultType.setAppData(resultAppData);
Holder<ResultMessageDataType> resultHolder = new Holder<ResultMessageDataType>();
resultHolder.value = resultType;
return resultHolder;
}
private boolean getEsiaRequestResult(Holder<ResultMessageDataType> result) {
List<Result> resultList = result.value.getAppData().getResult();
if (resultList != null && resultList.size() == 1) {
List<DataRow> dataRows = resultList.get(0).getDataRow();
if (dataRows != null && dataRows.size() == 1) {
log.info("ESIA AUTH. Response: " + dataRows.get(0).getValue());
return Boolean.valueOf(dataRows.get(0).getValue());
} else {
if (dataRows == null) {
log.info("ESIA AUTH. DataRows is null!");
} else {
log.info("ESIA AUTH. Wrong DataRows format. Count DataRows: " + resultList.size());
}
return false;
}
} else {
if (resultList == null) {
log.info("ESIA AUTH. Result is null!");
} else {
log.info("ESIA AUTH. Wrong result format. Count AppData: " + resultList.size());
}
return false;
}
}
private void sendRedirect(HttpServletResponse resp, String url) {
try {
resp.sendRedirect(url);
} catch (IOException e) {
log.severe("Не удалось сделать редирект на " + url + ": " + e.getMessage());
}
}
private void sendForward(HttpServletRequest req, HttpServletResponse resp, String url, String errorMessage) {
req.setAttribute("error", errorMessage);
try {
req.getRequestDispatcher(url).forward(req, resp);
} catch (ServletException e) {
log.severe("Не удалось перейти на на " + url + ": " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
log.severe("Не удалось перейти на на " + url + ": " + e.getMessage());
e.printStackTrace();
}
}
private void setPrincipal(HttpServletRequest req, Employee employee) {
String login = employee.getLogin();
Set<String> roles = Sets.newHashSet();
for (Role role : employee.getRoles()) {
roles.add(role.name());
}
HasRolePrincipal principal = new UserPrincipal(login, roles);
req.getSession().setAttribute(AuthorizationFilter.SESSION_ATTR_USER_PRINCIPAL, principal);
}
}