存Spring Security Login

建造一個Web不免的需要登入系統,登入系統不外乎就是使用Filter攔截每次的Request,判斷Session是否存在,若沒有則引導至登入頁面,這邊通常會加上一些控管,如timeout、repeat login等等問題,這些都是需要好好管控的,那在這邊我將會說明如何使用Security登入與登出。

POM



Security Config

package com.mvc.example.webconfig;

import javax.sql.DataSource;

import org.dom4j.swing.BranchTreeNode;
import org.hibernate.boot.registry.selector.SimpleStrategyRegistrationImpl;
import org.hibernate.loader.plan.exec.process.spi.ReturnReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;

import com.mvc.example.service.CustomUserDetailsService;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("andy").password("andy").roles("USER");
        auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("dba").password("dba").roles("ADMIN", "DBA");
    }

    @Bean
    public SessionRegistry sessionRegistry() {
        SessionRegistry sessionRegistry = new SessionRegistryImpl();
        return sessionRegistry;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/login").permitAll() //全部的人都可以嘗試登入
            .and()
                .formLogin() //這邊如果沒有使用下面的設定,Spring會自行產生簡易的登入頁面
                    .loginPage("/login") //登入頁面位置
                    .usernameParameter("username") //表單帳號參數名稱
                    .passwordParameter("password") //表單密碼參數名稱
                    .defaultSuccessUrl("/") //登入完成後導引至首頁
                    .permitAll() //此頁面沒有權限限制
            .and()
                .logout()
                    .logoutSuccessUrl("/login") //登出後跳轉至登入頁面
                    .invalidateHttpSession(true) //使該Session無效
            .and()
                .csrf() //使用csrf防禦機制
            .and()
                .sessionManagement() //管理Session  
                    .maximumSessions(1) //同時只能一個Session
                    .maxSessionsPreventsLogin(true) //只能讓一個帳號存在一個Session
                    .sessionRegistry(sessionRegistry()) //監聽Session的欄位,基本上預設即可,若要做更多用途可以自行撰寫
                    .and()
            .and()
                .exceptionHandling().accessDeniedPage("/403"); //將所有403頁面導向這裡 
    }
}

SecurityInit

這邊我也算是被雷到了,當初設定完後發現,登出後,居然就無法再登入了,原因就是這地方沒有做設定,詳細原因沒有查詢,有興趣自己看看唷!! 這邊是可以客製化的。

public class SecurityInit extends AbstractSecurityWebApplicationInitializer {

    @Override
    protected boolean enableHttpSessionEventPublisher() {
        return true;
    }
}

User Controller

@Controller
public class UserController {

    @RequestMapping(value = "/", method = RequestMethod.GET)  
    public String homePage(ModelMap model) {  
        model.addAttribute("greeting", "Hi, Welcome to mysite"); 
        return "welcome";  
    }  

    @RequestMapping(value = "/login", method = RequestMethod.GET)  
    public String loginPage() {  
        return "login";  
    }  

    @RequestMapping(value="/logout", method = RequestMethod.GET)  
    public String logoutPage (HttpServletRequest request, HttpServletResponse response, SessionRegistryImpl sessionRegistryImpl ) {  
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();  
        if (auth != null){      
            SecurityContextLogoutHandler securityContextLogoutHandler = new SecurityContextLogoutHandler();
            securityContextLogoutHandler.setInvalidateHttpSession(true);
            securityContextLogoutHandler.logout(request, response, auth);  
        }  
        return "redirect:/login?logout";  
    }  
}

JSP

welcome

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Hello Spring!</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</head>
<body>
    <div style="width:100%; background-color:#eee; padding: 12px 16px 0 0;">
        <security:authorize access="authenticated" var="authenticated">
            <security:authentication property="principal.username" var="username"/>
            <a href="/logout" style="float: right;"><button class="btn btn-danger">Logout</button></a>
        </security:authorize> 
        <%if(!(Boolean)pageContext.getAttribute("authenticated")) {%>
            <a href="/login" style="float: right; margin-right: 12px;"><button class="btn btn-success" style="">Login</button></a>
        <%} %>
    </div>
    <div class="jumbotron text-center">
        <h1>My Welcome Page</h1>
    </div>

    <div class="container">
      <div class="row">
        <div class="col-sm-4">
          <h3>Column 1</h3>
          <p>Lorem ipsum dolor..</p>
          <p>Ut enim ad..</p>
        </div>
        <div class="col-sm-4">
          <h3>Column 2</h3>
          <p>Lorem ipsum dolor..</p>
          <p>Ut enim ad..</p>
        </div>
        <div class="col-sm-4">
          <h3>Column 3</h3> 
          <p>Lorem ipsum dolor..</p>
          <p>Ut enim ad..</p>
        </div>
      </div>
    </div>
</body>
</html>

login

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Login page</title>

        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    </head>

    <body>
        <security:authorize access="authenticated" var="authenticated"></security:authorize> 
        <%if((Boolean)pageContext.getAttribute("authenticated")) {
            response.sendRedirect("/");
        } %>
        <div style="width: 100%; height:100%; display: flex; align-items: center;">
            <div style="width: 35%;  margin: 0 auto; box-shadow: 6px 6px 1px gray; padding: 28px;">
                <h3 style="text-align: center; margin-bottom: 20px;">Sign in to Spring Security</h3>
                <div class="login-form" style="margin: 0 auto; width: 100%;" >
                    <c:url var="loginUrl" value="/login" />
                    <form action="${loginUrl}" method="post" class="form-horizontal" style="margin: 0px;">
                        <c:if test="${param.error != null}">
                            <div class="alert alert-danger">
                                <p>Invalid username and password.</p>
                            </div>
                        </c:if>
                        <c:if test="${param.logout != null}">
                            <div class="alert alert-success">
                                <p>You have been logged out successfully.</p>
                            </div>
                        </c:if>
                        <label style="color: gray;">UserName</label>
                        <input type="text" class="form-control" style="margin-bottom: 12px;" id="username" name="username" required>
                        <label style="color: gray;">Password</label>
                        <input type="password" class="form-control" style="margin-bottom: 16px;" id="password" name="password" required>

                        <input type="hidden" name="${_csrf.parameterName}"
                            value="${_csrf.token}" />

                        <input type="submit" class="btn btn-block btn-primary btn-default" value="Log in">
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>

results matching ""

    No results matching ""