javascript
阐述Spring security实现用户认证授权的原理----基于session实现认证的方式
一.認(rèn)證流程
基于Session認(rèn)證方式的流程是,用戶認(rèn)證成功后,在服務(wù)端生成用戶相關(guān)的數(shù)據(jù)保存在session(當(dāng)前會話),而發(fā) 給客戶端 sesssion_id 存放到 cookie 中,這樣用客戶端請求時帶上 session_id 就可以驗證服務(wù)器端是否存在 session數(shù)據(jù),以此完成用戶的合法校驗。當(dāng)用戶退出系統(tǒng)或session過期銷毀時,客戶端的session_id也就無效了。
下圖是session認(rèn)證方式的流程圖:
二.創(chuàng)建工程
本案例工程使用maven進行構(gòu)建,使用SpringMVC、Servlet3.0實現(xiàn)
創(chuàng)建maven工程
創(chuàng)建maven工程 security-springmvc,工程結(jié)構(gòu)如下:
引入如下依賴如下,注意:
1、由于是web工程,packaging設(shè)置為war
2、使用tomcat7-maven-plugin插件來運行工程
3.Spring 容器配置
在config包下定義ApplicationConfig.java,它對應(yīng)web.xml中ContextLoaderListener的配置
package com.security.springmvc.config;import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller;/*** @author Administrator* @version 1.0**/ @Configuration //相當(dāng)于applicationContext.xml @ComponentScan(basePackages = "com.security.springmvc",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)}) public class ApplicationConfig {//在此配置除了Controller的其它bean,比如:數(shù)據(jù)庫鏈接池、事務(wù)管理器、業(yè)務(wù)bean等。 }4.servletContext配置
本案例采用Servlet3.0無web.xml方式,config包下定義WebConfig.java,它對應(yīng)于DispatcherServlet配置。
5.加載spring容器
在init包下定義Spring容器初始化類SpringApplicationInitializer,此類實現(xiàn)WebApplicationInitializer接口, Spring容器啟動時加載WebApplicationInitializer接口的所有實現(xiàn)類
package com.security.springmvc.init; import com.security.springmvc.config.ApplicationConfig; import com.security.springmvc.config.WebConfig; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; /*** @author Administrator* @version 1.0**/ public class SpringApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {//spring容器,相當(dāng)于加載 applicationContext.xml@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{ApplicationConfig.class};}//servletContext,相當(dāng)于加載springmvc.xml@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{WebConfig.class};}//url-mapping 攔截所有請求@Overrideprotected String[] getServletMappings() {return new String[]{"/"};} }SpringApplicationInitializer相當(dāng)于web.xml,使用了servlet3.0開發(fā)則不需要再定義web.xml, ApplicationConfig.class對應(yīng)以下配置的application-context.xml,WebConfig.class對應(yīng)以下配置的spring- mvc.xml,web.xml的內(nèi)容參考:
<web‐app><listener> <listener-class>org.springframework.web.context.ContextLoaderListene</listener‐class></listener><context‐param> <param‐name>contextConfigLocation</param‐name><param‐value>/WEB‐INF/application‐context.xml</param‐value> </context‐param> <servlet> <servlet‐name>springmvc</servlet‐name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet‐class> <init‐param> <param‐name>contextConfigLocation</param‐name> <param‐value>/WEB‐INF/spring‐mvc.xml</param‐value> </init‐param> <load‐on‐startup>1</load‐on‐startup> </servlet> <servlet‐mapping> <servlet‐name>springmvc</servlet‐name> <url‐pattern>/</url‐pattern> </servlet‐mapping></web‐app>三:實現(xiàn)認(rèn)證功能
1.認(rèn)證頁面
在webapp/WEB-INF/views下定義認(rèn)證頁面login.jsp,本案例只是測試認(rèn)證流程,頁面沒有添加css樣式,頁面實 現(xiàn)可填入用戶名,密碼,觸發(fā)登錄將提交表單信息至/login,內(nèi)容如下:
<%--Created by IntelliJ IDEA.User: 86187Date: 2021/5/18--%> <%@ page contentType="text/html;charset=UTF-8" pageEncoding="utf-8" %> <html><head><title>用戶登錄</title></head><body><form action="login" method="post">用戶名:<input type="text" name="username"><br>密 碼: <input type="password" name="password"><br><input type="submit" value="登錄"></form></body> </html>在WebConfig中新增如下配置,將/直接導(dǎo)向login.jsp頁面:
@Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("login");}
2.認(rèn)證接口
用戶進入認(rèn)證頁面,輸入賬號和密碼,點擊登錄,請求/login進行身份認(rèn)證。
(1)定義認(rèn)證接口,此接口用于對傳來的用戶名、密碼校驗,若成功則返回該用戶的詳細信息,否則拋出錯誤異 常:
認(rèn)證請求結(jié)構(gòu):
package com.security.springmvc.model;import lombok.Data;@Data public class AuthenticationRequest {//認(rèn)證請求的參數(shù) 賬號 密碼private String username;private String password; }認(rèn)證成功后返回的用戶詳細信息,也就是當(dāng)前登錄用戶的信息:
package com.security.springmvc.model;import lombok.AllArgsConstructor; import lombok.Data;@Data @AllArgsConstructor public class UserDto {public static final String SESSION_USER_KEY = "_user";//用戶的身份信息private String id;private String usernmae;private String password;private String fullname;private String mobile;}(2)認(rèn)證實現(xiàn)類,根據(jù)用戶名查找用戶信息,并校驗密碼,這里模擬了兩個用戶:
package com.security.springmvc.service;import com.security.springmvc.model.AuthenticationRequest; import com.security.springmvc.model.UserDto; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.util.HashMap; import java.util.Map;@Service public class AuthenticationServiceImpl implements AuthenticationService {/*** 功能:校驗用戶的身份信息是否合法* @param authenticationRequest 用戶認(rèn)證請求,賬號和密碼* @return*/@Overridepublic UserDto authentication(AuthenticationRequest authenticationRequest) {//1.校驗參數(shù)是否為空if (authenticationRequest==null|| StringUtils.isEmpty(authenticationRequest.getUsername())||StringUtils.isEmpty(authenticationRequest.getPassword())){throw new RuntimeException("賬號和密碼為空");}//根據(jù)賬號查詢數(shù)據(jù)庫,采用測試模擬的方法UserDto userDto = getUserDto(authenticationRequest.getUsername());//判斷用戶是否為空if (userDto==null){throw new RuntimeException("查詢不到該用戶");}//校驗密碼if(!authenticationRequest.getPassword().equals(userDto.getPassword())){throw new RuntimeException("賬號或者密碼錯誤");}//以上都可以,就代表密碼和用戶名輸入正確//認(rèn)證透過返回用戶的身份信息return userDto;}//根據(jù)賬號查詢用戶的信息private UserDto getUserDto(String userName){return userMap.get(userName);}//用戶信息private Map<String,UserDto> userMap=new HashMap<>();//靜態(tài)代碼塊{userMap.put("zhangsan",new UserDto("1010","zhangsan","123","張三","12345"));userMap.put("lisi",new UserDto("1010","zhangsan","123","張三","12345"));} }(3)登錄Controller,對/login請求處理,它調(diào)用AuthenticationService完成認(rèn)證并返回登錄結(jié)果提示信息:
package com.security.springmvc.controller;import com.security.springmvc.model.AuthenticationRequest; import com.security.springmvc.model.UserDto; import com.security.springmvc.service.AuthenticationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;@RestController public class LoginController {@AutowiredAuthenticationService authenticationService;//存文本類型@RequestMapping(value = "/login",produces = "text/plain;charset=utf-8")//用對象接收用戶傳入的數(shù)據(jù)public String login(AuthenticationRequest authenticationRequest, HttpSession session){UserDto userDto=authenticationService.authentication(authenticationRequest);//存入sessionsession.setAttribute(UserDto.SESSION_USER_KEY,userDto);return userDto.getUsernmae()+"登錄成功";}//測試用戶登錄成功的信息是否儲存在了session中@GetMapping(value = "/r/r1",produces = {"text/plain;charset=UTF-8"})public String r1(HttpSession session){String fullname=null;Object attribute = session.getAttribute(UserDto.SESSION_USER_KEY);if (attribute==null){fullname="匿名";}else{UserDto userDto = (UserDto) attribute;fullname=userDto.getFullname();}return fullname+"訪問資源r1";}//退出功能@GetMapping(value = "logout",produces = "text/plain;charset=UTF-8")public String logout(HttpSession session){//設(shè)置session無效的invalidatesession.invalidate();return "退出成功";} }(5)啟動項目測試
四:實現(xiàn)會話功能
會話是指用戶登入系統(tǒng)后,系統(tǒng)會記住該用戶的登錄狀態(tài),他可以在系統(tǒng)連續(xù)操作直到退出系統(tǒng)的過程認(rèn)證的目的是對系統(tǒng)資源的保護,每次對資源的訪問,系統(tǒng)必須得知道是誰在訪問資源,才能對該請求進行合法 攔截。因此,在認(rèn)證成功后,一般會把認(rèn)證成功的用戶信息放入Session中,在后續(xù)的請求中,系統(tǒng)能夠從Session中獲取到當(dāng)前用戶,用這樣的方式來實現(xiàn)會話機制。
(1)增加會話控制 首先在UserDto中定義一個SESSION_USER_KEY,作為Session中存放登錄用戶信息的key。
public static final String SESSION_USER_KEY = “_user”;
然后修改LoginController,認(rèn)證成功后,將用戶信息放入當(dāng)前會話。并增加用戶登出方法,登出時將session置為 失效。
package com.security.springmvc.controller;import com.security.springmvc.model.AuthenticationRequest; import com.security.springmvc.model.UserDto; import com.security.springmvc.service.AuthenticationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;@RestController public class LoginController {@AutowiredAuthenticationService authenticationService;//存文本類型@RequestMapping(value = "/login",produces = "text/plain;charset=utf-8")//用對象接收用戶傳入的數(shù)據(jù)public String login(AuthenticationRequest authenticationRequest, HttpSession session){UserDto userDto=authenticationService.authentication(authenticationRequest);//存入sessionsession.setAttribute(UserDto.SESSION_USER_KEY,userDto);return userDto.getUsernmae()+"登錄成功";}//測試用戶登錄成功的信息是否儲存在了session中@GetMapping(value = "/r/r1",produces = {"text/plain;charset=UTF-8"})public String r1(HttpSession session){String fullname=null;Object attribute = session.getAttribute(UserDto.SESSION_USER_KEY);if (attribute==null){fullname="匿名";}else{UserDto userDto = (UserDto) attribute;fullname=userDto.getFullname();}return fullname+"訪問資源r1";}//退出功能@GetMapping(value = "logout",produces = "text/plain;charset=UTF-8")public String logout(HttpSession session){//設(shè)置session無效的invalidatesession.invalidate();return "退出成功";} }(2)增加測試資源 修改LoginController,增加測試資源1,它從當(dāng)前會話session中獲取當(dāng)前登錄用戶,并返回提示信息給前臺。
package com.security.springmvc.controller;import com.security.springmvc.model.AuthenticationRequest; import com.security.springmvc.model.UserDto; import com.security.springmvc.service.AuthenticationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpSession;@RestController public class LoginController {@AutowiredAuthenticationService authenticationService;//存文本類型@RequestMapping(value = "/login",produces = "text/plain;charset=utf-8")//用對象接收用戶傳入的數(shù)據(jù)public String login(AuthenticationRequest authenticationRequest, HttpSession session){UserDto userDto=authenticationService.authentication(authenticationRequest);//存入sessionsession.setAttribute(UserDto.SESSION_USER_KEY,userDto);return userDto.getUsernmae()+"登錄成功";}//測試用戶登錄成功的信息是否儲存在了session中@GetMapping(value = "/r/r1",produces = {"text/plain;charset=UTF-8"})public String r1(HttpSession session){String fullname=null;Object attribute = session.getAttribute(UserDto.SESSION_USER_KEY);if (attribute==null){fullname="匿名";}else{UserDto userDto = (UserDto) attribute;fullname=userDto.getFullname();}return fullname+"訪問資源r1";}//退出功能@GetMapping(value = "logout",produces = "text/plain;charset=UTF-8")public String logout(HttpSession session){//設(shè)置session無效的invalidatesession.invalidate();return "退出成功";} }(3)測試
未登錄情況下直接訪問測試資源/r/r1:
成功登錄的情況下訪問測試資源/r/r1:
總結(jié)
以上是生活随笔為你收集整理的阐述Spring security实现用户认证授权的原理----基于session实现认证的方式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前后端分离 集群负载均衡 分布式
- 下一篇: Maven插件tomcat7-maver