简体   繁体   English

添加具有spring security的自定义登录控制器

[英]adding a custom login controller with spring security

An app built from the spring petclinic sample app has added spring security with a custom login form. 使用spring petclinic示例应用程序构建的应用程序通过自定义登录表单添加了弹簧安全性。

The app does not have a WebMvcConfiguration.java class as suggested by this tutorial . 该应用程序没有本教程建议的WebMvcConfiguration.java类。 Instead, it has the following line in mvc-core-config.xml : 相反,它在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. 我在eclipse中完成了Ctrl-H并在整个工作区中完成了一个关键词搜索术语/login ,但没有可见的控制器。 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. 我还查看了上面教程链接中提到的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";
}

In spring-security-core jar, there is an interface UserDetailsService which has a method 在spring-security-core jar中,有一个UserDetailsS​​ervice接口,它有一个方法

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>

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. 在配置元素中,您可以使用一个或多个元素限制对特定URL的访问。 Each element specifies a URL pattern and a set of access attributes required to access the URLs. 每个元素都指定访问URL所需的URL模式和一组访问属性。 Remember that you must always include a wildcard at the end of a URL pattern. 请记住,您必须始终在URL模式的末尾包含通配符。 Failing to do so will make the URL pattern unable to match a URL that has request parameters. 如果不这样做,将使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. 如果我们要描述一个没有任何安全性的url,那么我们应该从安全配置的xml文件下面的代码行中删除特定的url。 for example if we dont need any security for index page then the above coding should look like this. 例如,如果我们不需要索引页面的任何安全性,那么上面的编码应该是这样的。

<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>

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. 为此,您可以使用自己的CustomAuthenticationProvider,方法是从org.springframework。security。身份验证和覆盖公共身份验证身份验证(身份验证身份验证)方法实现AuthenticationProvider。

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 ie /login(POST) will be handled by this. 因此默认登录处理程序即/ login(POST)将由此处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM