crls = Collections.emptyList();
119 | CertStoreParameters revoked = new CollectionCertStoreParameters(crls);
120 | params.addCertStore(CertStore.getInstance("Collection", revoked));
121 |
122 | // If build() returns successfully, the certificate is valid.
123 | @SuppressWarnings("unused")
124 | CertPathBuilderResult r = CertPathBuilder.getInstance("PKIX").build(params);
125 | } catch (Exception ex) {
126 | log.debug("Certificate validation failed. ", ex);
127 | return false;
128 | } finally {
129 | try {
130 | stream.close();
131 | } catch (IOException e) {
132 | log.error("Could not close truststore stream.", e);
133 | }
134 | }
135 |
136 | return true;
137 | }
138 |
139 | public String getTrustStorePassword() {
140 | return trustStorePassword;
141 | }
142 |
143 | public void setTrustStorePassword(String trustStorePassword) {
144 | this.trustStorePassword = trustStorePassword;
145 | }
146 |
147 | public String getTrustStore() {
148 | return trustStore;
149 | }
150 |
151 | public void setTrustStore(String trustStore) {
152 | this.trustStore = trustStore;
153 | }
154 |
155 | public String getAccountToCertificateQuery() {
156 | return accountToCertificateQuery;
157 | }
158 |
159 | public void setAccountToCertificateQuery(String accountToCertificateQuery) {
160 | this.accountToCertificateQuery = accountToCertificateQuery;
161 | }
162 |
163 | public String getJndiDataSourceName() {
164 | return jndiDataSourceName;
165 | }
166 |
167 | public void setJndiDataSourceName(String jndiDataSourceName) {
168 | this.jndiDataSourceName = jndiDataSourceName;
169 | this.dataSource = getDataSourceFromJNDI(jndiDataSourceName);
170 | }
171 |
172 | private DataSource getDataSourceFromJNDI(String jndiDataSourceName) {
173 | try {
174 | InitialContext ic = new InitialContext();
175 | return (DataSource) ic.lookup(jndiDataSourceName);
176 | } catch (NamingException e) {
177 | log.error("JNDI error while retrieving " + jndiDataSourceName, e);
178 | throw new AuthorizationException(e);
179 | }
180 | }
181 |
182 | private String findUsernameToCertificate(String issuerName, BigInteger serialNumber) {
183 | String base64Serial = Base64.encode(serialNumber.toByteArray());
184 | return getAccountName(issuerName, base64Serial);
185 | }
186 |
187 | private String getAccountName(String issuerName, String base64Serial) {
188 | PreparedStatement statement = null;
189 | ResultSet resultSet = null;
190 | Connection conn = null;
191 | try {
192 | conn = dataSource.getConnection();
193 | statement = conn.prepareStatement(accountToCertificateQuery);
194 | statement.setString(1, base64Serial);
195 | statement.setString(2, issuerName);
196 |
197 | resultSet = statement.executeQuery();
198 |
199 | boolean hasAccount = resultSet.next();
200 | if (!hasAccount)
201 | return null;
202 |
203 | String username = resultSet.getString(1);
204 |
205 | if (resultSet.next()) {
206 | throw new AuthenticationException("More than one account for thre certificate.");
207 | }
208 |
209 | return username;
210 | } catch (SQLException e) {
211 | final String message = "There was a SQL error while authenticating user.";
212 | if (log.isErrorEnabled()) {
213 | log.error(message, e);
214 | }
215 | throw new AuthenticationException(message, e);
216 |
217 | } finally {
218 | JdbcUtils.closeResultSet(resultSet);
219 | JdbcUtils.closeStatement(statement);
220 | JdbcUtils.closeConnection(conn);
221 | }
222 | }
223 |
224 | public String getName() {
225 | return name;
226 | }
227 |
228 | public void setName(String name) {
229 | this.name = name;
230 | }
231 |
232 | }
233 |
--------------------------------------------------------------------------------
/src/main/java/org/meri/simpleshirosecuredapplication/sanitizer/Sanitizer.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication.sanitizer;
2 |
3 | import java.io.InputStream;
4 |
5 | import org.owasp.validator.html.AntiSamy;
6 | import org.owasp.validator.html.CleanResults;
7 | import org.owasp.validator.html.Policy;
8 | import org.owasp.validator.html.PolicyException;
9 | import org.owasp.validator.html.ScanException;
10 | /**
11 | * Sanitize user input into XSS attack safe string. The class is thread safe.
12 | */
13 | public class Sanitizer {
14 |
15 | private static final String POLICY_FILE_LOCATION = "/antisamy-tinymce-1.4.4.xml";
16 | private static Policy policy;
17 |
18 | public Sanitizer() {
19 | }
20 |
21 | public String sanitize(String dirtyInput) {
22 | AntiSamy as = new AntiSamy();
23 | try {
24 | CleanResults cr = as.scan(dirtyInput, getPolicy());
25 | return cr.getCleanHTML();
26 | } catch (ScanException e) {
27 | throw new RuntimeException(e);
28 | } catch (PolicyException e) {
29 | throw new RuntimeException(e);
30 | }
31 | }
32 |
33 | private Policy getPolicy() {
34 | if (policy==null) {
35 | try {
36 | InputStream resourceAsStream = getClass().getResourceAsStream(POLICY_FILE_LOCATION);
37 | policy = Policy.getInstance(resourceAsStream);
38 | } catch (PolicyException e) {
39 | throw new RuntimeException(e);
40 | }
41 | }
42 | return policy;
43 | }
44 |
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/meri/simpleshirosecuredapplication/servlet/AbstractFieldsHandlingServlet.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication.servlet;
2 |
3 | import javax.servlet.http.HttpServlet;
4 | import javax.servlet.http.HttpServletRequest;
5 |
6 | import org.meri.simpleshirosecuredapplication.sanitizer.Sanitizer;
7 |
8 | /**
9 | * Parent of all servlets reading user supplied data. Use {@link #getField(HttpServletRequest, String)}
10 | * to get fields values.
11 | *
12 | */
13 | @SuppressWarnings("serial")
14 | public abstract class AbstractFieldsHandlingServlet extends HttpServlet {
15 |
16 | private Sanitizer sanitizer = new Sanitizer();
17 |
18 | public AbstractFieldsHandlingServlet() {
19 | super();
20 | }
21 |
22 | /**
23 | * Reads sanitized request parameter value from request field.
24 | *
25 | * @param request http request
26 | * @param parameter name of request parameter
27 | *
28 | * @return request parameter value
29 | */
30 | protected String getField(HttpServletRequest request, String parameter) {
31 | String dirtyValue = request.getParameter(parameter);
32 | return sanitizer.sanitize(dirtyValue);
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/src/main/java/org/meri/simpleshirosecuredapplication/servlet/AccountPageServlet.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication.servlet;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.RequestDispatcher;
6 | import javax.servlet.ServletException;
7 | import javax.servlet.http.HttpServletRequest;
8 | import javax.servlet.http.HttpServletResponse;
9 |
10 | import org.apache.shiro.SecurityUtils;
11 | import org.meri.simpleshirosecuredapplication.model.ModelProvider;
12 | import org.meri.simpleshirosecuredapplication.model.UserPersonalData;
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | @SuppressWarnings("serial")
17 | public class AccountPageServlet extends AbstractFieldsHandlingServlet {
18 |
19 | private static final Logger log = LoggerFactory.getLogger(AccountPageServlet.class);
20 |
21 | @Override
22 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
23 | doPost(req, resp);
24 | }
25 |
26 | @Override
27 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
28 | String loggedPrincipal = (String) SecurityUtils.getSubject().getPrincipal();
29 | String firstname = getField(request, "firstname");
30 | String lastname = getField(request, "lastname");
31 | String about = getField(request, "about");
32 |
33 | try {
34 | saveData(loggedPrincipal, firstname, lastname, about);
35 | request.setAttribute(ServletConstants.actionResultMessage, "Saved was successful.");
36 | } catch (Exception ex) {
37 | log.error("Could not save data.", ex);
38 | request.setAttribute(ServletConstants.actionResultMessage, "Saved unsuccessful :(.");
39 | }
40 |
41 | // forward the request and response back to original page
42 | String originalPage = request.getParameter(ServletConstants.originalPage);
43 | RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(originalPage);
44 | dispatcher.forward(request, response);
45 | }
46 |
47 | private void saveData(String loggedPrincipal, String firstname, String lastname, String about) {
48 | ModelProvider mp = new ModelProvider();
49 | try {
50 | UserPersonalData data = mp.getCurrentUserData();
51 | mp.beginTransaction();
52 | if (data == null) {
53 | data = new UserPersonalData();
54 | updateUser(data, loggedPrincipal, firstname, lastname, about);
55 | mp.persist(data);
56 | } else {
57 | updateUser(data, loggedPrincipal, firstname, lastname, about);
58 | }
59 | mp.commit();
60 | } finally {
61 | mp.close();
62 | }
63 | }
64 |
65 | private void updateUser(UserPersonalData data, String loggedPrincipal, String firstname, String lastname, String about) {
66 | data.setUserName(loggedPrincipal);
67 | data.setFirstname(firstname);
68 | data.setLastname(lastname);
69 | data.setAbout(about);
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/org/meri/simpleshirosecuredapplication/servlet/CertificateOrFormAuthenticationFilter.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication.servlet;
2 |
3 | import java.security.cert.X509Certificate;
4 |
5 | import javax.servlet.ServletRequest;
6 | import javax.servlet.ServletResponse;
7 |
8 | import org.apache.shiro.authc.AuthenticationException;
9 | import org.apache.shiro.authc.AuthenticationToken;
10 | import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
11 | import org.meri.simpleshirosecuredapplication.authc.X509CertificateUsernamePasswordToken;
12 |
13 | public class CertificateOrFormAuthenticationFilter extends FormAuthenticationFilter {
14 |
15 | @Override
16 | protected boolean isLoginSubmission(ServletRequest request, ServletResponse response) {
17 | return super.isLoginSubmission(request, response) || isCertificateLogInAttempt(request, response);
18 | }
19 |
20 | private boolean isCertificateLogInAttempt(ServletRequest request, ServletResponse response) {
21 | return hasCertificate(request) && !getSubject(request, response).isAuthenticated();
22 | }
23 |
24 | private boolean hasCertificate(ServletRequest request) {
25 | return null != getCertificate(request);
26 | }
27 |
28 | private X509Certificate getCertificate(ServletRequest request) {
29 | X509Certificate[] attribute = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
30 | return attribute == null ? null : attribute[0];
31 | }
32 |
33 | @Override
34 | protected AuthenticationToken createToken(String username, String password, ServletRequest request, ServletResponse response) {
35 | boolean rememberMe = isRememberMe(request);
36 | String host = getHost(request);
37 | X509Certificate certificate = getCertificate(request);
38 | return createToken(username, password, rememberMe, host, certificate);
39 | }
40 |
41 | protected AuthenticationToken createToken(String username, String password, boolean rememberMe, String host, X509Certificate certificate) {
42 | return new X509CertificateUsernamePasswordToken(username, password, rememberMe, host, certificate);
43 | }
44 |
45 | @Override
46 | protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
47 | String message = ae.getMessage();
48 | request.setAttribute(getFailureKeyAttribute(), message);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/org/meri/simpleshirosecuredapplication/servlet/PerformFunctionAndGoBackServlet.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication.servlet;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.RequestDispatcher;
6 | import javax.servlet.Servlet;
7 | import javax.servlet.ServletException;
8 | import javax.servlet.http.HttpServlet;
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletResponse;
11 |
12 | import org.apache.log4j.Logger;
13 | import org.apache.shiro.ShiroException;
14 | import org.meri.simpleshirosecuredapplication.actions.Actions;
15 |
16 | public class PerformFunctionAndGoBackServlet extends HttpServlet implements Servlet {
17 |
18 | private static transient final Logger log = Logger.getLogger(PerformFunctionAndGoBackServlet.class);
19 |
20 | private static final long serialVersionUID = -7896114563632467947L;
21 |
22 | @Override
23 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
24 | doPost(req, resp);
25 | }
26 |
27 | @Override
28 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
29 | String action = request.getParameter("action");
30 | String actionResult = performAction(action);
31 | request.setAttribute(ServletConstants.actionResultMessage, actionResult);
32 |
33 | // forward the request and response back to original page
34 | String originalPage = request.getParameter(ServletConstants.originalPage);
35 | RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(originalPage);
36 | dispatcher.forward(request, response);
37 | }
38 |
39 | private String performAction(String actionName) {
40 | try {
41 | Actions action = findAction(actionName);
42 | String result = action == null ? null : action.doIt();
43 | log.debug("Performed function with result: " + result);
44 | return result;
45 | } catch (ShiroException ex) {
46 | log.debug("Function failed with " + ex.getMessage() + " message.");
47 | return "Error: " + ex.getMessage();
48 | }
49 | }
50 |
51 | private Actions findAction(String actionName) {
52 | if (actionName == null)
53 | return null;
54 |
55 | Actions[] values = Actions.values();
56 |
57 | for (Actions action : values) {
58 | if (actionName.equals(action.getName()))
59 | return action;
60 | }
61 | return null;
62 | }
63 |
64 | public String getUrl(HttpServletRequest request) {
65 | String reqUrl = request.getRequestURL().toString();
66 | String queryString = request.getQueryString(); // d=789
67 | if (queryString != null) {
68 | reqUrl += "?" + queryString;
69 | }
70 | return reqUrl;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/org/meri/simpleshirosecuredapplication/servlet/ServletConstants.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication.servlet;
2 |
3 | public class ServletConstants {
4 |
5 | public static final String originalPage = "originalPage";
6 | public static final String actionResultMessage = "actionResultMessage";
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/org/meri/simpleshirosecuredapplication/servlet/VerboseFormAuthenticationFilter.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication.servlet;
2 |
3 | import javax.servlet.ServletRequest;
4 |
5 | import org.apache.shiro.authc.AuthenticationException;
6 | import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
7 |
8 | public class VerboseFormAuthenticationFilter extends FormAuthenticationFilter {
9 |
10 | @Override
11 | protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
12 | String message = ae.getMessage();
13 | request.setAttribute(getFailureKeyAttribute(), message);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/resources/Shiro.ini:
--------------------------------------------------------------------------------
1 | [main]
2 | # realms to be used
3 | certificateRealm=org.meri.simpleshirosecuredapplication.realm.X509CertificateRealm
4 | certificateRealm.trustStore=src/main/resources/truststore
5 | certificateRealm.trustStorePassword=secret
6 | certificateRealm.jndiDataSourceName=jdbc/SimpleShiroSecuredApplicationDB
7 |
8 | saltedJdbcRealm=org.meri.simpleshirosecuredapplication.realm.JNDIAndSaltAwareJdbcRealm
9 | # any object property is automatically configurable in Shiro.ini file
10 | saltedJdbcRealm.jndiDataSourceName=jdbc/SimpleShiroSecuredApplicationDB
11 | # the realm should handle also authorization
12 | saltedJdbcRealm.permissionsLookupEnabled=true
13 | # If not filled, subclasses of JdbcRealm assume "select password from users where username = ?"
14 | # first result column is password, second result column is salt
15 | saltedJdbcRealm.authenticationQuery = select password, salt from sec_users where name = ?
16 | # If not filled, subclasses of JdbcRealm assume "select role_name from user_roles where username = ?"
17 | saltedJdbcRealm.userRolesQuery = select role_name from sec_users_roles where user_name = ?
18 | # If not filled, subclasses of JdbcRealm assume "select permission from roles_permissions where role_name = ?"
19 | saltedJdbcRealm.permissionsQuery = select permissions from sec_roles_permissions where role_name = ?
20 |
21 | # password hashing specification, put something big for hasIterations
22 | sha256Matcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
23 | sha256Matcher.hashAlgorithmName=SHA-256
24 | sha256Matcher.hashIterations=1
25 | saltedJdbcRealm.credentialsMatcher = $sha256Matcher
26 |
27 | # filter configuration
28 | certificateFilter = org.meri.simpleshirosecuredapplication.servlet.CertificateOrFormAuthenticationFilter
29 | # request parameter with login error information; if not present filter assumes 'shiroLoginFailure'
30 | certificateFilter.failureKeyAttribute=simpleShiroApplicationLoginFailure
31 | # specify login page
32 | certificateFilter.loginUrl = /simpleshirosecuredapplication/account/login.jsp
33 | # name of request parameter with username; if not present filter assumes 'username'
34 | certificateFilter.usernameParam = user
35 | # name of request parameter with password; if not present filter assumes 'password'
36 | certificateFilter.passwordParam = pass
37 | # does the user wish to be remembered?; if not present filter assumes 'rememberMe'
38 | certificateFilter.rememberMeParam = remember
39 | # redirect after successful login
40 | certificateFilter.successUrl = /simpleshirosecuredapplication/account/personalaccountpage.jsp
41 |
42 | # roles filter: redirect to error page if user does not have access rights
43 | roles.unauthorizedUrl = /simpleshirosecuredapplication/account/accessdenied.jsp
44 |
45 | # multi-realms strategy
46 | # authenticationStrategy=org.meri.simpleshirosecuredapplication.authc.PrimaryPrincipalSameAuthenticationStrategy
47 | # securityManager.authenticator.authenticationStrategy=$authenticationStrategy
48 |
49 | [urls]
50 | # force ssl for login page
51 | /simpleshirosecuredapplication/account/login.jsp=ssl[8443], certificateFilter
52 |
53 | # only users with some roles are allowed to use role-specific pages
54 | /simpleshirosecuredapplication/repairmen/**=certificateFilter, roles[repairman]
55 | /simpleshirosecuredapplication/sales/**=certificateFilter, roles[sales]
56 | /simpleshirosecuredapplication/scientists/**=certificateFilter, roles[scientist]
57 | /simpleshirosecuredapplication/adminarea/**=certificateFilter, roles[Administrator]
58 |
59 | # enable certificateFilter filter for all application pages
60 | /simpleshirosecuredapplication/**=certificateFilter
61 |
--------------------------------------------------------------------------------
/src/main/resources/antisamy-tinymce-1.4.4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
28 |
29 |
30 |
32 |
33 |
34 |
36 |
37 |
39 |
40 |
41 |
42 |
49 |
50 |
54 |
55 |
56 |
57 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
81 |
82 |
83 |
84 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
97 |
98 |
99 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | g
115 | grin
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
--------------------------------------------------------------------------------
/src/main/resources/db.changelog.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 | Create table structure for users, passwords, roles and permissions.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
44 |
45 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
61 |
62 |
63 |
64 |
65 |
66 | Create initial users, roles and permissions.
67 |
68 |
69 |
70 |
72 |
73 |
74 |
75 |
76 |
78 |
79 |
80 |
81 |
82 |
84 |
85 |
86 |
87 |
88 |
90 |
91 |
92 |
93 |
94 |
96 |
97 |
98 |
99 |
100 |
102 |
103 |
104 |
105 |
106 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 | Add certificate unique id to sec_users table.
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 | Associate certificates with initial user accounts.
185 |
186 |
187 |
188 |
189 | name='administrator'
190 |
191 |
192 |
193 |
194 | name='friendlyrepairman'
195 |
196 |
197 |
198 |
199 | name='unfriendlyrepairman'
200 |
201 |
202 |
203 |
204 | name='mathematician'
205 |
206 |
207 |
208 |
209 | name='servicessales'
210 |
211 |
212 |
213 |
214 | name='productsales'
215 |
216 |
217 |
218 |
219 | name='physicien'
220 |
221 |
222 |
223 |
224 |
225 | Add user personal data such as first name, last name, hobby etc to the application.
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
245 |
246 |
247 |
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Licensed to the Apache Software Foundation (ASF) under one
3 | # or more contributor license agreements. See the NOTICE file
4 | # distributed with this work for additional information
5 | # regarding copyright ownership. The ASF licenses this file
6 | # to you under the Apache License, Version 2.0 (the
7 | # "License"); you may not use this file except in compliance
8 | # with the License. You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing,
13 | # software distributed under the License is distributed on an
14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | # KIND, either express or implied. See the License for the
16 | # specific language governing permissions and limitations
17 | # under the License.
18 | #
19 | # This file is used to format all logging output
20 | log4j.rootLogger=TRACE, stdout
21 |
22 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender
23 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
24 | log4j.appender.stdout.layout.ConversionPattern=%d %-5p [%c]: %m%n
25 |
26 | # =============================================================================
27 | # 3rd Party Libraries
28 | # OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL
29 | # =============================================================================
30 | # ehcache caching manager:
31 | log4j.logger.net.sf.ehcache=WARN
32 |
33 | # Most all Apache libs:
34 | log4j.logger.org.apache=WARN
35 |
36 | # Quartz Enterprise Scheular (java 'cron' utility)
37 | log4j.logger.org.quartz=WARN
38 |
39 | # =============================================================================
40 | # Apache Shiro
41 | # =============================================================================
42 | # Shiro security framework
43 | log4j.logger.org.apache.shiro=TRACE
44 | #log4j.logger.org.apache.shiro.realm.text.PropertiesRealm=INFO
45 | #log4j.logger.org.apache.shiro.cache.ehcache.EhCache=INFO
46 | #log4j.logger.org.apache.shiro.io=INFO
47 | #log4j.logger.org.apache.shiro.web.servlet=INFO
48 | log4j.logger.org.apache.shiro.util.ThreadContext=INFO
49 |
--------------------------------------------------------------------------------
/src/main/resources/truststore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/main/resources/truststore
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/classes/META-INF/persistence.xml:
--------------------------------------------------------------------------------
1 |
3 |
5 | org.apache.openjpa.persistence.PersistenceProviderImpl
6 |
7 | jdbc/SimpleShiroSecuredApplicationDB
8 |
9 | org.meri.simpleshirosecuredapplication.model.UserPersonalData
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/jetty-web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | jdbc/SimpleShiroSecuredApplicationDB
7 |
8 |
9 | ../SimpleShiroSecuredApplicationDatabase
10 | create
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Simple Secure Application
7 |
8 |
9 |
10 | PerformFunctionAndGoBackServlet
11 | org.meri.simpleshirosecuredapplication.servlet.PerformFunctionAndGoBackServlet
12 | 1
13 |
14 |
15 |
16 | AccountPageServlet
17 | org.meri.simpleshirosecuredapplication.servlet.AccountPageServlet
18 | 1
19 |
20 |
21 |
22 | PerformFunctionAndGoBackServlet
23 | /simpleshirosecuredapplication/masterservlet
24 |
25 |
26 |
27 | AccountPageServlet
28 | /simpleshirosecuredapplication/accountpageservlet
29 |
30 |
31 |
32 | index.jsp
33 |
34 |
35 |
36 |
37 |
38 | ShiroFilter
39 | org.apache.shiro.web.servlet.IniShiroFilter
40 |
41 | configPath
42 | classpath:Shiro.ini
43 |
44 |
45 |
46 |
47 | ShiroFilter
48 | /*
49 |
50 |
51 |
52 |
53 |
54 |
55 | Derby Connection
56 | jdbc/SimpleShiroSecuredApplicationDB
57 | javax.sql.DataSource
58 | Container
59 |
60 |
61 |
62 |
63 | liquibase.changelog
64 | src/main/resources/db.changelog.xml
65 |
66 |
67 |
68 | liquibase.datasource
69 | jdbc/SimpleShiroSecuredApplicationDB
70 |
71 |
72 |
74 |
75 | liquibase.integration.servlet.LiquibaseServletListener
76 |
77 |
78 |
79 | persistence/SimpleShiroSecuredApplicationPU
80 | SimpleShiroSecuredApplicationPU
81 |
82 |
83 |
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
4 | Welcome
5 | Simple web application for trying out Shiro security framework. There is no security yet.
6 | ">login
7 | ">all application functions
8 | ">view all accounts
9 | ">personal account page
10 | ">administrators page
11 | ">repairmen page
12 | ">sales page
13 | ">scientists page
14 | ">logout
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/account/accessdenied.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 |
4 |
5 |
6 |
7 | Access Denied
8 |
9 |
10 | <%@include file="/simpleshirosecuredapplication/common/commonformstuff.jsp" %>
11 | Sorry, you do not have access rights to that area.
12 |
13 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/account/allapplicationfunctions.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 |
4 |
5 |
6 |
7 | All Application Functions
8 |
9 |
10 | <%@page import="org.meri.simpleshirosecuredapplication.actions.Actions"%>
11 |
12 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/account/login.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 |
4 |
5 |
6 |
7 | Please Log In
8 |
9 |
10 | <%@include file="/simpleshirosecuredapplication/common/commonformstuff.jsp" %>
11 | <%
12 | String errorDescription = (String) request.getAttribute("simpleShiroApplicationLoginFailure");
13 | if (errorDescription!=null) {
14 | %>
15 | Login attempt was unsuccessful: <%=errorDescription%>
16 | <%
17 | }
18 | %>
36 |
37 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/account/logout.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 |
4 |
5 |
6 |
7 | Logout
8 |
9 |
10 | <%@include file="/simpleshirosecuredapplication/common/commonformstuff.jsp" %>
11 | <%@ page import="org.apache.shiro.SecurityUtils" %>
12 | <% SecurityUtils.getSubject().logout();%>
13 | You have successfully logged out.
14 |
15 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/account/personalaccountpage.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 |
4 |
5 |
6 |
13 |
14 | Personal Account
15 |
16 |
17 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/account/viewallaccounts.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 | <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
4 |
5 |
6 |
7 |
8 |
9 | View All Accounts
10 |
11 |
12 | <%@include file="/simpleshirosecuredapplication/common/commonformstuff.jsp" %>
13 | <%@page import="org.apache.shiro.SecurityUtils"%>
14 | <%@page import="org.meri.simpleshirosecuredapplication.model.ModelProvider"%>
15 | <%@page import="org.meri.simpleshirosecuredapplication.model.UserPersonalData"%>
16 | <%@page import="java.util.List"%>
17 | All users with filled account data:
18 | <%
19 | ModelProvider mp = new ModelProvider();
20 | List usersData = mp.getAllUsersData();
21 | pageContext.setAttribute("allusers", usersData);
22 | mp.close();
23 | %>
24 |
25 | <%
26 | for (UserPersonalData data : usersData) {
27 | %>
28 | - <%=data.getFirstname()%> <%=data.getLastname()%>
29 |
30 |
31 | <% } %>
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/adminarea/administratorspage.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 |
4 |
5 |
6 |
7 | Administrator Page
8 |
9 |
10 | <%@page import="org.meri.simpleshirosecuredapplication.actions.Actions"%>
11 |
12 |
39 |
40 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/common/commonformstuff.jsp:
--------------------------------------------------------------------------------
1 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2 | ">Go Home
3 | ">logout
4 | <%
5 | String reqUrl = request.getServletPath().toString();
6 | String actionMessage = (String) request.getAttribute("actionResultMessage");
7 | if (actionMessage!=null) {
8 | %>
9 | <%=actionMessage %>
10 | <%} %>
11 |
12 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/index.jsp:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/repairmen/repairmen.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 |
4 |
5 |
6 |
7 | Repairmen Page
8 |
9 |
10 | <%@page import="org.meri.simpleshirosecuredapplication.actions.Actions"%>
11 |
12 |
39 |
40 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/sales/sales.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 |
4 |
5 |
6 |
7 | Sales Page
8 |
9 |
10 | <%@page import="org.meri.simpleshirosecuredapplication.actions.Actions"%>
11 |
12 |
39 |
40 |
--------------------------------------------------------------------------------
/src/main/webapp/simpleshirosecuredapplication/scientists/scientists.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
2 | pageEncoding="ISO-8859-1"%>
3 |
4 |
5 |
6 |
7 | Scientists Page
8 |
9 |
10 | <%@page import="org.meri.simpleshirosecuredapplication.actions.Actions"%>
11 |
12 |
39 |
40 |
--------------------------------------------------------------------------------
/src/test/java/org/meri/simpleshirosecuredapplication/RunWaitTest.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication;
2 |
3 | import java.io.IOException;
4 | import java.net.MalformedURLException;
5 |
6 | import org.junit.Test;
7 | import org.meri.simpleshirosecuredapplication.test.AbstractContainerTest;
8 |
9 | import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
10 |
11 | public class RunWaitTest extends AbstractContainerTest {
12 |
13 | @Test
14 | public void sleepForever() throws FailingHttpStatusCodeException, MalformedURLException, IOException, InterruptedException {
15 | while (true)
16 | Thread.sleep(9999);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/org/meri/simpleshirosecuredapplication/test/AbstractContainerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 | package org.meri.simpleshirosecuredapplication.test;
20 |
21 | import static org.junit.Assert.assertTrue;
22 |
23 | import org.junit.Before;
24 | import org.junit.BeforeClass;
25 | import org.mortbay.jetty.Connector;
26 | import org.mortbay.jetty.Server;
27 | import org.mortbay.jetty.nio.SelectChannelConnector;
28 | import org.mortbay.jetty.security.SslSocketConnector;
29 | import org.mortbay.jetty.webapp.WebAppContext;
30 |
31 | import com.gargoylesoftware.htmlunit.WebClient;
32 |
33 | public abstract class AbstractContainerTest {
34 | protected static PauseableServer server;
35 |
36 | protected static final int port = 9180;
37 | protected static final int sslPort = 8443;
38 |
39 | protected static final String BASEURI = "http://localhost:" + port + "/";
40 |
41 | protected final WebClient webClient = new WebClient();
42 |
43 | private static String[] configurationClasses =
44 | {
45 | "org.mortbay.jetty.webapp.JettyWebXmlConfiguration",
46 | "org.mortbay.jetty.webapp.WebInfConfiguration",
47 | "org.mortbay.jetty.plus.webapp.EnvConfiguration",
48 | "org.mortbay.jetty.plus.webapp.Configuration",
49 | "org.mortbay.jetty.webapp.TagLibConfiguration"
50 | } ;
51 |
52 |
53 | @BeforeClass
54 | public static void startContainer() throws Exception {
55 | if (server == null) {
56 | server = new PauseableServer();
57 | Connector connector = createHttpConnector();
58 | SslSocketConnector sslConnector = createSslConnector();
59 | server.setConnectors(new Connector[]{connector, sslConnector});
60 |
61 | WebAppContext context = createWebAppContext();
62 | server.setHandler(context);
63 |
64 | server.start();
65 | assertTrue(server.isStarted());
66 | }
67 | }
68 |
69 | private static WebAppContext createWebAppContext() {
70 | WebAppContext context = new WebAppContext("src/main/webapp", "/");
71 | context.setConfigurationClasses(configurationClasses);
72 |
73 | return context;
74 | }
75 |
76 | private static SslSocketConnector createSslConnector() {
77 | SslSocketConnector sslConnector = new SslSocketConnector();
78 | sslConnector.setPort(sslPort);
79 | sslConnector.setKeyPassword("secret");
80 | sslConnector.setKeystore("src/test/resources/keystore");
81 | sslConnector.setTrustPassword("secret");
82 | sslConnector.setTruststore("src/main/resources/truststore");
83 | sslConnector.setPassword("secret");
84 | sslConnector.setWantClientAuth(true);
85 | //sslConnector.setNeedClientAuth(true);
86 |
87 | return sslConnector;
88 | }
89 |
90 | private static Connector createHttpConnector() {
91 | Connector connector = new SelectChannelConnector();
92 | connector.setPort(port);
93 | return connector;
94 | }
95 |
96 | @Before
97 | public void beforeTest() {
98 | webClient.setThrowExceptionOnFailingStatusCode(true);
99 | }
100 |
101 | public void pauseServer(boolean paused) {
102 | if (server != null) server.pause(paused);
103 | }
104 |
105 | public static class PauseableServer extends Server {
106 | public synchronized void pause(boolean paused) {
107 | try {
108 | if (paused) for (Connector connector : getConnectors())
109 | connector.stop();
110 | else for (Connector connector : getConnectors())
111 | connector.start();
112 | } catch (Exception e) {
113 | }
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/test/java/org/meri/simpleshirosecuredapplication/util/AnalyzeKeystore.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication.util;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.IOException;
5 | import java.math.BigInteger;
6 | import java.security.KeyStore;
7 | import java.security.cert.X509Certificate;
8 | import java.util.Enumeration;
9 |
10 | import org.apache.xerces.impl.dv.util.Base64;
11 |
12 | /**
13 | * Utility class. Investigates keystore file and prints all certificates along with authority names and serial numbers.
14 | */
15 | public class AnalyzeKeystore {
16 |
17 | public static void main(String[] args) {
18 | AnalyzeKeystore instance = new AnalyzeKeystore();
19 | instance.certificateOK("src/main/resources/truststore", "secret");
20 | }
21 |
22 | private void certificateOK(String truststore, String password) {
23 | FileInputStream stream = null;
24 |
25 | try {
26 | stream = new FileInputStream(truststore);
27 | KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
28 | keyStore.load(stream, password.toCharArray());
29 |
30 | Enumeration aliases = keyStore.aliases();
31 | while (aliases.hasMoreElements()) {
32 | String alias = aliases.nextElement();
33 | X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias);
34 |
35 | BigInteger serialNumber = certificate.getSerialNumber();
36 | String issuerName = certificate.getIssuerDN().getName();
37 | String base64Serial = Base64.encode(serialNumber.toByteArray());
38 |
39 | System.out.println(alias + ": " + base64Serial + "|XX|" + issuerName);
40 | }
41 |
42 | } catch (Exception ex) {
43 | ex.printStackTrace();
44 | } finally {
45 | try {
46 | stream.close();
47 | } catch (IOException e) {
48 | }
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/java/org/meri/simpleshirosecuredapplication/util/HashPassword.java:
--------------------------------------------------------------------------------
1 | package org.meri.simpleshirosecuredapplication.util;
2 |
3 | import org.apache.shiro.crypto.hash.Sha256Hash;
4 | import org.apache.shiro.util.SimpleByteSource;
5 |
6 | public class HashPassword {
7 |
8 | /**
9 | * @param args
10 | */
11 | public static void main(String[] args) {
12 | simpleHash("heslo");
13 | simpleSaltedHash("administrator", "heslo");
14 | simpleSaltedHash("friendlyrepairman", "heslo");
15 | simpleSaltedHash("unfriendlyrepairman", "heslo");
16 | simpleSaltedHash("mathematician", "heslo");
17 | simpleSaltedHash("physicien", "heslo");
18 | simpleSaltedHash("productsales", "heslo");
19 | simpleSaltedHash("servicessales", "heslo");
20 |
21 | }
22 |
23 | private static String simpleHash(String password) {
24 | Sha256Hash sha256Hash = new Sha256Hash(password);
25 | String result = sha256Hash.toHex();
26 |
27 | System.out.println("Simple hash: " + result);
28 | return result;
29 | }
30 |
31 | private static String simpleSaltedHash(String username, String password) {
32 | Sha256Hash sha256Hash = new Sha256Hash(password, (new SimpleByteSource("random_salt_value_" + username)).getBytes());
33 | String result = sha256Hash.toHex();
34 |
35 | System.out.println(username + " simple salted hash: " + result);
36 | return result;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/resources/clients/administrator/administrator.cer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/administrator/administrator.cer
--------------------------------------------------------------------------------
/src/test/resources/clients/administrator/administrator.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/administrator/administrator.jks
--------------------------------------------------------------------------------
/src/test/resources/clients/administrator/administrator.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/administrator/administrator.p12
--------------------------------------------------------------------------------
/src/test/resources/clients/friendlyrepaiman/friendlyrepairman.cer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/friendlyrepaiman/friendlyrepairman.cer
--------------------------------------------------------------------------------
/src/test/resources/clients/friendlyrepaiman/friendlyrepairman.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/friendlyrepaiman/friendlyrepairman.jks
--------------------------------------------------------------------------------
/src/test/resources/clients/friendlyrepaiman/friendlyrepairman.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/friendlyrepaiman/friendlyrepairman.p12
--------------------------------------------------------------------------------
/src/test/resources/clients/mathematician/mathematician.cer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/mathematician/mathematician.cer
--------------------------------------------------------------------------------
/src/test/resources/clients/mathematician/mathematician.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/mathematician/mathematician.jks
--------------------------------------------------------------------------------
/src/test/resources/clients/mathematician/mathematician.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/mathematician/mathematician.p12
--------------------------------------------------------------------------------
/src/test/resources/clients/physicien/physicien.cer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/physicien/physicien.cer
--------------------------------------------------------------------------------
/src/test/resources/clients/physicien/physicien.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/physicien/physicien.jks
--------------------------------------------------------------------------------
/src/test/resources/clients/physicien/physicien.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/physicien/physicien.p12
--------------------------------------------------------------------------------
/src/test/resources/clients/productsales/productsales.cer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/productsales/productsales.cer
--------------------------------------------------------------------------------
/src/test/resources/clients/productsales/productsales.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/productsales/productsales.jks
--------------------------------------------------------------------------------
/src/test/resources/clients/productsales/productsales.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/productsales/productsales.p12
--------------------------------------------------------------------------------
/src/test/resources/clients/servicessales/servicessales.cer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/servicessales/servicessales.cer
--------------------------------------------------------------------------------
/src/test/resources/clients/servicessales/servicessales.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/servicessales/servicessales.jks
--------------------------------------------------------------------------------
/src/test/resources/clients/servicessales/servicessales.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/servicessales/servicessales.p12
--------------------------------------------------------------------------------
/src/test/resources/clients/unfriendlyrepaiman/unfriendlyrepairman.cer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/unfriendlyrepaiman/unfriendlyrepairman.cer
--------------------------------------------------------------------------------
/src/test/resources/clients/unfriendlyrepaiman/unfriendlyrepairman.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/unfriendlyrepaiman/unfriendlyrepairman.jks
--------------------------------------------------------------------------------
/src/test/resources/clients/unfriendlyrepaiman/unfriendlyrepairman.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/clients/unfriendlyrepaiman/unfriendlyrepairman.p12
--------------------------------------------------------------------------------
/src/test/resources/keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/src/test/resources/keystore
--------------------------------------------------------------------------------
/target/test-classes/keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SomMeri/SimpleShiroSecuredApplication/778f37b22fb023873a13976860e3692c55dce424/target/test-classes/keystore
--------------------------------------------------------------------------------