Spring Security 自定义过滤器
我想自定义 Spring security 3.0.5 并将登录 URL 更改为 /login 而不是 /j_spring_security_check。
我需要做的是允许登录“/”目录并保护“/admin/report.html”页面。
首先,我使用教程和 Spring Security 源代码创建自己的过滤器:
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 中进行以下更改
<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。
<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 时,我被重定向到登录页面。 但提交凭据后,我得到:
HTTP Status 404 - /SpringMVC/login/
type Status report
message /SpringMVC/login/
description The requested resource (/SpringMVC/login/) is not available.
看起来我的配置有问题,但我无法弄清楚导致此问题的原因。 你能帮忙吗?
I would like to customize Spring security 3.0.5 and change login URL to be /login instead of /j_spring_security_check.
What I need to do, is to to allow login to "/" directory and to secure "/admin/report.html" page.
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);
}
}
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>
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>
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我在这方面迟了大约 12 个月,但为了自定义 Spring Security 表单登录的登录 URL,您不需要创建自己的过滤器。 form-login 标签的属性之一允许您设置自定义 URL。事实上,您还可以使用 form-login 标记的属性更改默认的 j_username 和 j_password 字段名称。这是一个例子:
I'm about 12 months late on this one, but in order to customise the login URL of the Spring Security form login you don't need to create your own filter. One of the attributes of the form-login tag allows you to set a custom URL. In fact, you can also change the default j_username and j_password field names using attributes of the form-login tag. Here's an example:
我认为 @Ischin 对表单操作 url 的疑问是正确的。尝试输入完整路径,看看是否有效。如果确实如此,您可以从那里找出不匹配的内容。
我唯一能想到要检查的是 web.xml 中的过滤器映射。由于您正在点击登录页面,因此您已经进行了此设置,但我会检查您是否不仅拦截具有特定扩展名的网址等。
另外,仅供参考,如果您想要请求(一旦登录表单验证了user)转到受保护的资源(在本例中为/admin/report.html),那么您应该删除表单:登录always-use-default-target =“true”。将此标志设置为 true 将导致请求始终转到默认目标 url,这通常不是您想要的。来自 spring 安全文档 :
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.
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.
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: