java Spring Security 自定义过滤器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5971453/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Security custom filter
提问by danny.lesnik
I would like to customize Spring security 3.0.5 and change login URL to be /login instead of /j_spring_security_check.
我想自定义 Spring security 3.0.5 并将登录 URL 更改为 /login 而不是 /j_spring_security_check。
What I need to do, is to to allow login to "/" directory and to secure "/admin/report.html" page.
我需要做的是允许登录到“/”目录并保护“/admin/report.html”页面。
First of All I create my own filter using tutorial and Spring Security source code:
首先,我使用教程和 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);
}
}
after It I'm making the following changes in xml
在它之后我在 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.
然后我的代码有 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>
when trying to navigate to /admin/report.html I'm redirected to login page. but after submitting credentials I'm getting:
尝试导航到 /admin/report.html 时,我被重定向到登录页面。但在提交凭据后,我得到:
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?
看起来我的配置有问题,但我无法弄清楚是什么导致了这个问题。你能帮我吗?
采纳答案by Matt
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.
我认为@Ischin 想知道表单操作 url 是正确的。尝试输入完整路径,看看是否有效。如果是,您可以从那里开始找出不匹配的内容。
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.
我唯一能想到的检查是 web.xml 中的过滤器映射。由于您正在访问登录页面,因此您已进行此设置,但我会检查您是否不仅拦截了具有特定扩展名等的网址。
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:
此外,就像仅供参考,如果您希望请求(一旦登录表单对用户进行身份验证)转到受保护的资源(在本例中为 /admin/report.html),那么您应该删除表单:login always-use-默认目标=“真”。将此标志设置为 true 将导致请求始终转到默认目标 url,这通常不是您想要的。来自spring 安全文档:
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.
映射到 UsernamePasswordAuthenticationFilter 的 defaultTargetUrl 属性。如果未设置,则默认值为“/”(应用程序根)。如果用户在尝试访问受保护资源时未被要求登录,则登录后将被带到此 URL,当他们将被带到最初请求的 URL 时。
回答by Alessandro Giannone
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:
我在这方面晚了大约 12 个月,但是为了自定义 Spring Security 表单登录的登录 URL,您不需要创建自己的过滤器。form-login 标签的属性之一允许您设置自定义 URL。实际上,您还可以使用 form-login 标记的属性更改默认的 j_username 和 j_password 字段名称。下面是一个例子:
<form-login login-page="/login" login-processing-url="/login.do" default-target-url="/" always-use-default-target="true" authentication-failure-url="/login?error=1" username-parameter="username" password-parameter="password"/>