Pagpapatuloy ng unang bahagi ng artikulo tungkol sa JAAS. Alamin natin kung posibleng gumamit lang ng mga anotasyon para sa JAAS, at kung anong mga problema ang makakaharap natin. Malalaman natin sa bahaging ito kung aling mga tool ng Servlet API ang nagpapahintulot sa amin na gawing mas unibersal ang code. At ibuod natin ang ating nabasa.
pagpapatuloy
Sa unang bahagi ng pagsusuri ng teknolohiya ng JAAS (tingnan ang " JAAS - Panimula sa Teknolohiya (Bahagi 1) ") tiningnan namin ang pangunahing kaso ng paggamit para sa JAAS at ang Servlet API. Nakita namin na pinamahalaan ng lalagyan ng servlet ng Tomcat ang seguridad ng aming web application gamit ang arkitektura ng JAAS. Ang pagkakaroon ng kaalaman sa "auth-method" at "Security Realm", ang Tomcat container mismo ay nagbigay sa amin ng kinakailangang pagpapatupad ng mekanismo ng pagpapatunay at mismong nagbigay sa amin ng CallbackHandler, ginamit lang namin ang lahat ng ito sa aming login module. Ang tanging mahalagang bagay na dapat tandaan ay ang browser ay nagse-save ng login at password data na ipinadala sa pamamagitan ng BASIC authentication. Samakatuwid, para sa bawat bagong pag-scan gamit ang Chrome, maaari mong pindutin ang Ctrl+Shift+N upang magbukas ng bagong window para gumana sa incognito mode.Mga anotasyon
Matagal nang hindi uso ang configuration gamit ang XML. Samakatuwid, mahalagang sabihin na simula sa Servlet API na bersyon 3.0, mayroon kaming pagkakataong magtakda ng mga setting ng servlet gamit ang mga anotasyon, nang hindi ginagamit ang web.xml deployment descriptor file. Tingnan natin kung paano magbabago ang pamamahala sa seguridad kung gagamit tayo ng mga anotasyon. At posible bang ipatupad ang inilarawan na mga diskarte sa itaas gamit ang mga anotasyon? Ang detalye ng Servlet API at ang seksyong " Mga Anotasyon at kakayahang magamit " ay muling makakatulong sa amin na maunawaan ang mga anotasyon . Sinasabi ng seksyong ito na ang isang deklarasyon ng servletweb.xml
ay maaaring mapalitan ng isang anotasyon @WebServlet
. Alinsunod dito, magiging ganito ang hitsura ng aming servlet:
@WebServlet(name="app", urlPatterns = "/secret")
public class App extends HttpServlet {
Susunod, tingnan natin ang kabanata " 13.3 Programmatic Security ". Sinasabi nito na maaari rin kaming magdeklara ng Security Constraint sa pamamagitan ng mga anotasyon:
@WebServlet(name="app", urlPatterns = "/secret")
@ServletSecurity(httpMethodConstraints = {
@HttpMethodConstraint(value = "GET", rolesAllowed = "admin")
})
public class App extends HttpServlet {
Ngayon web.xml
ay mayroon na lamang isang bloke na natitira sa atin - login-config
. Ang problema ay nagkataon lamang na walang paraan upang madali at simpleng palitan ito. Dahil sa malapit na koneksyon sa pagitan ng mga setting ng seguridad ng web application at mga setting ng seguridad ng web server, walang simple at unibersal na paraan para gawin ito, kahit na sa programmatically. Isa ito sa mga problema sa pagpapatunay gamit ang JAAS at Servlet API. Sa pagsasalita tungkol sa block login-config
, ito ay nagkakahalaga ng pag-unawa na ito ay isang deklaratibong paglalarawan ng Mga Mekanismo ng Pagpapatunay, i.e. mga mekanismo ng pagpapatunay. Wala pa ring simpleng unibersal na paraan para palitan ito, dahil... Ang pagproseso web.xml
ay nangyayari nang malalim sa loob ng mga lalagyan ng servlet. Halimbawa, sa Tomcat maaari mong tingnan ang pinagmulan ContextConfig.java . Samakatuwid, kahit na para sa lalagyan ng servlet ng Tomcat mayroong ilang mga pagpipilian at lahat sila ay naiiba. Halimbawa, kung gagamitin namin ang Embedded Tomcat servlet container (i.e. nagtataas kami ng web server mula sa code), maaari mong basahin ang tungkol sa mga opsyon dito: " Naka-embed na Tomcat na may pangunahing pagpapatunay sa pamamagitan ng code ". Bilang karagdagan, ang isang pangkalahatang halimbawa ng pagpapalaki ng Embedde Tomcat ay makikita sa Heroku PaaS platform guide: " Lumikha ng Java Web Application Gamit ang Embedded Tomcat ". Kung ang Tomcat ay hindi ginagamit sa Embedded mode, pagkatapos ay para sa Tomcat maaari kang gumamit ng isang karaniwang ginagamit na diskarte - mga tagapakinig ng kaganapan. Sa Tomcat ito ay " The LifeCycle Listener Component ". Kasabay nito, mahalagang maunawaan na ang mga lalagyan ng servlet (sa aming kaso Tomcat) ay maaaring may sariling mga loader ng klase at hindi posible na kunin at gamitin ang iyong mga klase. Para sa Tomcat kailangan mong maunawaan ang " Class Loader HOW-TO ". Sa isa pang servlet container na tinatawag na Undertow, ito ay maaaring makamit gamit ang " Servlet Extensions ". Tulad ng nakikita mo, ang ilan ay nagbigay ng mas nababaluktot na mekanismo, habang ang iba ay hindi. Tulad ng nakikita mo, walang iisang pagpipilian. Lahat sila ay ibang-iba. Posible bang gumawa ng isang bagay na unibersal gamit lamang ang Servlet API at JAAS? Sa Internet makakahanap ka ng panukalang gumamit ng Servlet Filter para magsagawa ng authentication nang walang block login-config
. Sa wakas, isaalang-alang natin ang pagpipiliang ito. Ito ay magbibigay-daan sa amin na ulitin kung paano gumagana ang JAAS.
Awth Filter
Kaya, ang aming layunin ay ganap na maalisweb.xml
ang file. Kung aalisin natin ito, kung gayon, sa kasamaang-palad, hindi na natin magagamit ang Security Constraint, dahil ang kanilang pagproseso ay maaaring mangyari nang mas maaga kaysa sa paglalapat ng mga servlet filter. Ito ang bayad na kailangan mong bayaran para sa "versatility" ng paggamit ng mga filter. Yung. kailangan naming alisin ang anotasyon @ServletSecurity
, at ang lahat ng mga pagsusuri na dati naming inilarawan sa hadlang sa seguridad ay kailangang isagawa sa programmatically. Tulad ng nakikita mo, ang pagpipiliang ito ay nagpapataw din ng maraming hindi kasiya-siyang paghihigpit sa amin. Una sa lahat, alisin natin ang anotasyon @ServletSecurity
mula sa mapagkukunan at ang bloke login-config
mula sa web.xml
. Ngayon, kami mismo ang kailangang magpatupad ng Basic authentication. Ngayon, idagdag natin ang ating filter:
@WebFilter("/*")
public class JaasFilter implements javax.servlet.Filter {
Sa ngayon ay tila simple. Sumulat tayo ng paraan ng pagsisimula:
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String jaas_conf = filterConfig.getServletContext().getRealPath("/WEB-INF/jaas.config");
System.getProperties().setProperty("java.security.auth.login.config",jaas_conf);
}
Tulad ng nakikita mo, napipilitan na kaming gumamit ng mga pangunahing tool ng JAAS upang maghanap para sa jaas config file. Ito ay may malaking disbentaha - kung mayroong maraming mga application, maaaring masira ng isang application ang pagpapatunay ng isa pa. Sa pangkalahatan, kung paano ka makakapagtakda ng Jaas Config file ay inilarawan nang detalyado sa dokumentasyon ng JAAS: " Appendix A: Mga Setting ng JAAS sa java.security Security Properties File ". Susunod, ilalarawan namin ang mismong paraan ng pag-filter. Magsimula tayo sa pagtanggap ng kahilingan sa HTTP:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
// Если в реквесте уже есть Principal - ничего не делаем
if (req.getUserPrincipal() != null ) {
chain.doFilter(request, response);
}
Simple lang ang lahat dito. Kung available ang Principal, matagumpay ang pag-authenticate. Susunod, kailangan mong ilarawan ang mga pagkilos ng filter kapag hindi naipasa ng user ang pagpapatunay, i.e. hindi pa siya nakikilala. Noong nakaraan, inilarawan namin ang pangunahing paraan ng pagpapatunay, BASIC. kasi Dahil kami na ngayon ang nagsusulat ng filter, kakailanganin naming malaman kung paano gumagana ang BASIC authentication. Maaari mong gamitin ang " MDN web docs: HTTP authorization ". At gayundin ang " Paano Gumagana ang HTTP Authentication? " Mula sa paglalarawan kung paano gumagana ang Basic authentication, malinaw na kung gusto ng server na magsagawa ng BASIC authentication, at hindi nagbigay ng data ang user, magpapadala ang server ng espesyal na header na "WWW-Authenticate" at error code 401. Gumawa tayo ng isang panloob na pamamaraan para dito:
private void requestNewAuthInResponse(ServletResponse response) throws IOException {
HttpServletResponse resp = (HttpServletResponse) response;
String value = "Basic realm=\"JaasLogin\"";
resp.setHeader("WWW-Authenticate", value);
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
Ngayon gamitin natin ang pamamaraang ito at idagdag doFilter
ang sumusunod na bloke ng code sa pamamaraan:
// Получаем security Header. А если его нет - запрашиваем
String secHeader = req.getHeader("authorization");
if (secHeader == null) {
requestNewAuthInResponse(response);
}
Ngayon magdagdag tayo ng isang sangay para sa if
, na isasagawa kapag naipadala na ang header:
// Проверяем аутентификацию
else {
String authorization = secHeader.replace("Basic ", "");
Base64.Decoder decoder = java.util.Base64.getDecoder();
authorization = new String(decoder.decode(authorization));
String[] loginData = authorization.split(":");
try {
if (loginData.length == 2) {
req.login(loginData[0], loginData[1]);
chain.doFilter(request, response);
} else {
requestNewAuthInResponse(response);
}
} catch (ServletException e) {
requestNewAuthInResponse(response);
}
}
Maaari kang magdagdag ng pahintulot sa code na ito, halimbawa: req.isUserInRole("admin")
Kaya nagsagawa kami ng pagpapatunay sa iyo gamit ang isang filter. Sa isang banda, maraming code at manu-manong pagproseso. Sa kabilang banda, mayroong versatility at pagsasarili ng server.
GO TO FULL VERSION