Spring Security自定义过滤器
我想自定义Spring security 3.0.5并将登录URL更改为/ login而不是/ j_spring_security_check。
I would like to customize Spring security 3.0.5 and change login URL to be /login instead of /j_spring_security_check.
我需要做的是允许登录/目录并保护/admin/report.html页面。
What I need to do, is to to allow login to "/" directory and to secure "/admin/report.html" page.
首先,我使用教程和Spring Security源代码创建自己的过滤器:
First of All I create my own filter using tutorial and Spring Security source code:
public class MyFilter extends AbstractAuthenticationProcessingFilter {
private static final String DEFAULT_FILTER_PROCESSES_URL = "/login";
private static final String POST = "POST";
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
protected MyFilter() {
super(DEFAULT_FILTER_PROCESSES_URL);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
HttpSession session = request.getSession(false);
if (session != null || getAllowSessionCreation()) {
request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextEscapeUtils.escapeEntities(username));
}
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
if (request.getMethod().equals(POST)) {
// If the incoming request is a POST, then we send it up
// to the AbstractAuthenticationProcessingFilter.
super.doFilter(request, response, chain);
} else {
// If it's a GET, we ignore this request and send it
// to the next filter in the chain. In this case, that
// pretty much means the request will hit the /login
// controller which will process the request to show the
// login page.
chain.doFilter(request, response);
}
}
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
}
之后我在xml中进行了以下更改
after It I'm making the following changes in xml
<security:http auto-config="true">
<!--<session-management session-fixation-protection="none"/>-->
<security:custom-filter ref="myFilter" before="FORM_LOGIN_FILTER"/>
<security:intercept-url pattern="/admin/login.jsp*" filters="none"/>
<security:intercept-url pattern="/admin/report.html" access="ROLE_ADMIN"/>
<security:form-login login-page="/admin/login.jsp" login-processing-url="/login" always-use-default-target="true"/>
<security:logout logout-url="/logout" logout-success-url="/login.jsp" invalidate-session="true"/>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider>
<security:password-encoder hash="md5" />
<security:user-service>
<!-- peter/opal -->
<security:user name="peter" password="22b5c9accc6e1ba628cedc63a72d57f8" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<bean id="myFilter" class="com.vanilla.springMVC.controllers.MyFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
然后我的JSP带有我的代码。
and then I have JSP with my code.
<form action="../login" method="post">
<label for="j_username">Username</label>
<input type="text" name="j_username" id="j_username" />
<br/>
<label for="j_password">Password</label>
<input type="password" name="j_password" id="j_password"/>
<br/>
<input type='checkbox' name='_spring_security_remember_me'/> Remember me on this computer.
<br/>
<input type="submit" value="Login"/>
</form>
尝试导航到/admin/report.html时,我被重定向到登录页面。
但在提交凭证后我得到:
when trying to navigate to /admin/report.html I'm redirected to login page. but after submitting credentials I'm getting:
HTTP Status 404 - /SpringMVC/login/
type Status report
message /SpringMVC/login/
description The requested resource (/SpringMVC/login/) is not available.
看起来我的配置有问题,但我无法弄清楚导致这种情况的原因。
你能帮帮忙吗?
It looks like I have problem in configuration, but I can't figure it out what causing this. Can you help?
我认为@Ischin对表格动作网址的疑问是正确的。尝试放入完整路径,看看是否有效。如果是这样,你可以从那里找出不匹配的东西。
I think that @Ischin is correct to wonder about the form action url. Try putting in the full path and see if that works. If it does, you can work from there to figure out what isn't matching up.
我能想到要检查的另一件事是你的过滤器映射web.xml中。由于您正在登录页面,因此您已设置此设置,但我会检查您是否不仅截取具有特定扩展名的网址等。
The only other thing I can think of to check is the filter mapping in you web.xml. Since you are hitting the login page you have this set up, but I would check that you're not only intercepting urls with specific extensions, etc.
此外,就像如果您想要请求(一旦登录表单对用户进行身份验证)转到安全资源(在这种情况下为/admin/report.html),那么您应该删除表单:login always-use-default-target = 真正。将此标志设置为true将导致请求始终转到默认目标URL,这通常不是您想要的。来自弹簧安全文档 :
Also, just as an fyi, if you want the request (once the login form authenticates the user) to go to the secured resource (/admin/report.html in this case) then you should remove the form:login always-use-default-target="true". Setting this flag to true will cause the request to always go to the default target url, which usually isn't what you want. From the spring security docs:
映射到defaultTargetUrl属性
UsernamePasswordAuthenticationFilter。
如果未设置,则默认值为/
(应用程序根目录)。登录后,用户将获得
到此URL,
,前提是他们在尝试访问安全
资源时未被要求登录
,当他们将被带到$时b $ b最初请求的URL。
Maps to the defaultTargetUrl property of UsernamePasswordAuthenticationFilter. If not set, the default value is "/" (the application root). A user will be taken to this URL after logging in, provided they were not asked to login while attempting to access a secured resource, when they will be taken to the originally requested URL.