Java 添加具有 spring 安全性的自定义登录控制器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32019353/
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
adding a custom login controller with spring security
提问by CodeMed
An app built from the spring petclinic sample apphas added spring security with a custom login form.
从spring petclinic 示例应用程序构建的应用程序添加了带有自定义登录表单的 spring 安全性。
The app does not have a WebMvcConfiguration.java class as suggested by this tutorial. Instead, it has the following line in mvc-core-config.xml
:
该应用程序没有本教程建议的 WebMvcConfiguration.java 类。相反,它在以下行中mvc-core-config.xml
:
<mvc:view-controller path="/login" view-name="login" />
I have done Ctrl-H
in eclipse and done a key word search for the term /login
in the entire workspace, but no controller is visible. I also looked in the messages-jc
sample project referred to in the tutorial link above, but could not find a "/login
" controller there either.
我已经Ctrl-H
在 Eclipse 中完成/login
并在整个工作区中对该术语进行了关键字搜索,但没有控制器可见。我还查看了messages-jc
上面教程链接中提到的示例项目,但也找不到“ /login
”控制器。
How can I add a controller that will perform spring authentication with the standard username and password, but that will also allow me to subsequently add additional code to the authentication process when the login form at the "/login" url is submitted?
如何添加一个控制器,该控制器将使用标准用户名和密码执行 spring 身份验证,但这也允许我随后在“/login”url 上的登录表单提交时向身份验证过程添加其他代码?
Is it as simple as adding the following to SomeOtherController.java
:
是否像添加以下内容一样简单SomeOtherController.java
:
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String showLoginForm(Model model) {
//what goes here?
return "public/loginform";
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String processLoginForm(HttpSession session, @ModelAttribute("user") User user,
BindingResult result, Model model, final RedirectAttributes redirectAttributes)
{
//what goes here?
return "secure/main";
}
回答by Obi Wan - PallavJha
In spring-security-core jar, there is an interface UserDetailsService which has a method
在 spring-security-core jar 中,有一个接口 UserDetailsService,它有一个方法
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
You can implement this interface and create your code your own logic, like
您可以实现此接口并创建您自己的逻辑代码,例如
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) {
User user = userService.findUserByUsername(username);
if (user != null) {
String password = user.getPassword();
boolean enabled = user.getActive();
boolean accountNonExpired = user.getActive();
boolean credentialsNonExpired = user.getActive();
boolean accountNonLocked = user.getActive();
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (Role r : user.getRoles()) {
authorities.add(new SimpleGrantedAuthority(r.getAuthority()));
}
org.springframework.security.core.userdetails.User securedUser = new org.springframework.security.core.userdetails.User(
username, password, enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, authorities);
return securedUser;
} else {
throw new UsernameNotFoundException(
"Unable to find user with username provided!!");
}
}
and then create an object of DaoAuthenticationProvider using
然后使用创建 DaoAuthenticationProvider 的对象
<bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"></property>
</bean>
Finally, supply this DaoAuthenticationProvider to ProviderManager
最后,将此 DaoAuthenticationProvider 提供给 ProviderManager
<bean class="org.springframework.security.authentication.ProviderManager">
<constructor-arg>
<list>
<ref bean="daoAuthenticationProvider" />
</list>
</constructor-arg>
</bean>
<security:authentication-manager>
<security:authentication-provider
user-service-ref="userDetailsService">
<security:password-encoder hash="plaintext"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
adding web.xml details
添加 web.xml 详细信息
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-config/spring-*.xml</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
回答by MS Ibrahim
Your jsp file involving login form should be like this.
你的涉及登录表单的jsp文件应该是这样的。
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Spring security</title>
<style>
.errorblock {
color: #ff0000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
</head>
<body onload='document.f.j_username.focus();'>
<h3>Login with Username and Password</h3>
<c:if test="${not empty error}">
<div class="errorblock">
Your login attempt was not successful, try again.
Caused :
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
</div>
</c:if>
<%-- <c:url value="/j_spring_security_check" var="index.htm" />
<form name='f' action="${index.htm}" method='POST'> --%>
<form name='f' action="<c:url value='j_spring_security_check' />" method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='j_username' value=''>
</td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='j_password' />
</td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit"
value="submit" />
</td>
</tr>
<tr>
<td colspan='2'><input name="reset" type="reset" />
</td>
</tr>
</table>
</form>
</body>
</html>
Your spring-security.xml file should look like this.
您的 spring-security.xml 文件应如下所示。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http auto-config="true" >
<security:intercept-url pattern="/index*" access="ROLE_USER" />
<security:form-login login-page="/login.htm" default-target-url="/index.htm"
authentication-failure-url="/loginerror.htm" />
<security:logout logout-success-url="/logout.htm" />
<!-- <security:csrf disabled="true"/> -->
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<!-- <security:user-service>
<security:user name="syed" password="1111" authorities="ROLE_USER" />
</security:user-service> -->
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username, password, active from users where username=?"
authorities-by-username-query="select us.username, ur.authority from users us, user_roles ur
where us.user_id = ur.user_id and us.username =? "
/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
Inside the configuration element, you can restrict access to particular URLs with one or more elements. Each element specifies a URL pattern and a set of access attributes required to access the URLs. Remember that you must always include a wildcard at the end of a URL pattern. Failing to do so will make the URL pattern unable to match a URL that has request parameters.
在配置元素中,您可以使用一个或多个元素限制对特定 URL 的访问。每个元素指定一个 URL 模式和一组访问 URL 所需的访问属性。请记住,您必须始终在 URL 模式的末尾包含通配符。如果不这样做,则 URL 模式将无法匹配具有请求参数的 URL。
<security:http auto-config="true" >
<security:intercept-url pattern="/index*" access="ROLE_USER" />
<security:intercept-url pattern="/Transit*" access="ROLE_USER" />
<security:form-login login-page="/login.htm" default-target-url="/index.htm"
authentication-failure-url="/loginerror.htm" />
<security:logout logout-success-url="/logout.htm" />
</security:http>
When ever we are going to describe a url without any security, Then we should remove the particular url from the above lines of code under security configured xml file. for example if we dont need any security for index page then the above coding should look like this.
当我们要描述一个没有任何安全性的 url 时,那么我们应该从安全配置的 xml 文件下的上述代码行中删除特定的 url。例如,如果我们不需要索引页面的任何安全性,那么上面的编码应该是这样的。
<security:http auto-config="true" >
<security:intercept-url pattern="/Transit*" access="ROLE_USER" />
<security:form-login login-page="/login.htm" default-target-url="/index.htm"
authentication-failure-url="/loginerror.htm" />
<security:logout logout-success-url="/logout.htm" />
</security:http>
回答by Shashank.sahu11
For this purpose you can use your own CustomAuthenticationProvider by implementing AuthenticationProvider from org.?springframework.?security.?authentication and override public Authentication authenticate(Authentication authentication) method.
为此,您可以通过从 org.?springframework.?security.?authentication 实现 AuthenticationProvider 来使用自己的 CustomAuthenticationProvider 并覆盖 public Authentication authenticate(Authentication authentication) 方法。
code example is given below
代码示例如下
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
List<GrantedAuthority> grantedAuths = new ArrayList<>();
//validate and do your additionl logic and set the role type after your validation. in this code i am simply adding admin role type
grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN" ));
return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
}
@Override
public boolean supports(Class<?> arg0) {
return true;
}
}
so default login handler i.e. /login(POST) will be handled by this.
因此默认登录处理程序即 /login(POST) 将由此处理。