基于session的認(rèn)證授權(quán)方式-SSM

基于session的認(rèn)證授權(quán)方式-SSM

    具體流程:當(dāng)用戶登陸成功后,會(huì)在服務(wù)端將用戶的相關(guān)信息保存到session中,而將發(fā)給客戶端的session_id保存到cookie中,這樣下次請(qǐng)求時(shí)帶上session_id來(lái)校驗(yàn)服務(wù)端是否存在session數(shù)據(jù),如果存在就校驗(yàn)通過(guò),如果不存在就校驗(yàn)失敗。當(dāng)用戶退出登錄或session數(shù)據(jù)過(guò)期,就需要重新登錄。

本案例工程使用maven進(jìn)行構(gòu)建,使用SpringMVC、Servlet3.0實(shí)現(xiàn)。

  • 導(dǎo)入spring-webmvc,javax.servlet-api依賴(lài)
    <!--打成war可運(yùn)行在tomcat中-->
    <packaging>war</packaging>
    <!-- 設(shè)置jdk1.8編譯 -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <!-- webmvc依賴(lài) servlet依賴(lài) -->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <hostName>localhost</hostName>        <!--   Default: localhost -->
                    <port>8080</port>                     <!-- 啟動(dòng)端口 Default:8080 -->
                    <path>/</path>   <!-- 訪問(wèn)應(yīng)用路徑  Default: /${project.artifactId}-->
                    <uriEncoding>UTF-8</uriEncoding>      <!-- uri編碼 Default: ISO-8859-1 -->
                </configuration>
            </plugin>
        </plugins>
    </build>
  • 定義spring容器配置類(lèi)
//spring容器配置 相當(dāng)于applicationContext.xml
@Configuration
//組件掃描springmvc包 排除controller包
@ComponentScan(basePackages = "com.gyf.security.springmvc"
            ,excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)})
public class ApplicationConfig {
    //將配置文件中的配置拿到類(lèi)中來(lái)配置
    //配置除了Controller的其他bean,如數(shù)據(jù)庫(kù)連接池,事務(wù)管理器,業(yè)務(wù)bean等

}
  • 定義springmvc配置類(lèi)
//servletContext配置  /相當(dāng)于springvc.xml文件
//該類(lèi)實(shí)現(xiàn)WebMvcConfigurer接口進(jìn)行配置
//組件掃描springmvc包,包含Controller包
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.gyf.security.springmvc"
            ,includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class))
public class WebConfig implements WebMvcConfigurer {
    //視圖解析器
    @Bean
    public InternalResourceViewResolver viewResolver(){
        InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
        internalResourceViewResolver.setPrefix("/WEB-INF/view/");
        internalResourceViewResolver.setSuffix(".jsp");
        return internalResourceViewResolver;
    }
    //添加視圖控制器
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("login");
    }
    @Autowired
    private SimpleAuthenticationInterceptor simpleAuthenticationInterceptor;
    //添加攔截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //對(duì)指定的url進(jìn)行攔截
        registry.addInterceptor(simpleAuthenticationInterceptor).addPathPatterns("/r/**");
    }
}
  • 手動(dòng)加載spring配置文件
//手動(dòng)加載spring配置類(lèi)
//該類(lèi)繼承AbstractAnnotationConfigDispatcherServletInitializer,此類(lèi)實(shí)現(xiàn)WebApplicationInitializer接口,Spring容器啟動(dòng)時(shí)加載WebApplicationInitializer接口的所有實(shí)現(xiàn)類(lèi)
public class SpringApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    //加載spring容器 加載ApplicationContext.xml
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{ApplicationConfig.class};
    }
    //servletContext 加載springmvc.xml
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }
    //url-mapping
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
  • 自定義認(rèn)證頁(yè)面 lgoin.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
<html>
<head>
    <title>用戶登錄</title>
</head>
<body>
<form action="login" method="post">
    用戶名:<input type="text" name="username"><br>
    密&nbsp;&nbsp;&nbsp;碼:
    <input type="password" name="password"><br>
    <input type="submit" value="登錄">
</form>
</body>
</html>
  • 創(chuàng)建兩個(gè)實(shí)體類(lèi) UserDto,AuthenticationRequest并添加get、set方法,構(gòu)造方法
//用戶表
public class AuthenticationRequest {
    //用戶名
    private String username;
    //密碼
    private String password;
}
//用戶具體信息表
public class UserDto {
    public static final String SESSION_USER_KEY ="_user";
    //用戶身份信息
    private String id;
    private String username;
    private String password;
    private String fullname;
    private String mobile;
    /**
     * 用戶的權(quán)限
     */
    private Set<String> authorities;
}
  • 業(yè)務(wù)層Service 自定義認(rèn)證服務(wù)用于用戶的身份認(rèn)證
public interface AuthenticationService {
    //用戶認(rèn)證
    UserDto authentication(AuthenticationRequest request);
}
@Service
public class AuthenticationServiceImpl implements AuthenticationService {
    /**
     * 用戶認(rèn)證
     * @param request
     * @return
     */
    @Override
    public UserDto authentication(AuthenticationRequest request) {
        //校驗(yàn)參數(shù)是否為空
         if (request==null || StringUtils.isEmpty(request.getUsername()) || StringUtils.isEmpty(request.getPassword())){
             throw new RuntimeException("賬號(hào)或密碼為空");
         }
         //根據(jù)用戶和密碼去查詢數(shù)據(jù)庫(kù) 模擬數(shù)據(jù)庫(kù)
        UserDto userDto = this.getUserDto(request.getUsername());
         //判斷用戶是否為空
        if (userDto==null){
            throw new RuntimeException("查詢不到該用戶");
        }
        //校驗(yàn)密碼
        if (!request.getPassword().equals(userDto.getPassword())){
            throw new RuntimeException("密碼錯(cuò)誤");
        }
        //認(rèn)證通過(guò) 返回用戶的身份信息
        return userDto;
    }

    //用戶信息 假裝到數(shù)據(jù)庫(kù)獲取數(shù)據(jù)
    private Map<String,UserDto> map = new HashMap<>();
    //代碼塊
    {
        Set<String> authorities1 = new HashSet<>();
        authorities1.add("p1");
        Set<String> authorities2 = new HashSet<>();
        authorities2.add("p2");
        map.put("zhangsan",new UserDto("1010","zhangsan","123456","張三","123456",authorities1));
        map.put("lisi",new UserDto("1001","lisi","123","李四","789456",authorities2));
    }
    
    //根據(jù)賬號(hào)查詢用戶信息
    private UserDto getUserDto(String username){
        UserDto userDto = map.get(username);
        return userDto;
    }
}
  • 表現(xiàn)層Controller 僅測(cè)試用
//@Controller+@ResponseBody
@RestController
public class LoginController {
    @Autowired
    private AuthenticationService authenticationService;

    //produces 存文本類(lèi)型
    @RequestMapping(value = "/login",produces = "text/plain;charset=utf-8")
    public String login(AuthenticationRequest request, HttpSession httpSession){
        UserDto userDto = authenticationService.authentication(request);
        //將用戶信息存入session
        httpSession.setAttribute(UserDto.SESSION_USER_KEY,userDto);
        return userDto.getUsername()+"登陸成功";
    }
    /**
     * 刪除session中的數(shù)據(jù)
     * @param session
     * @return
     */
    @GetMapping(value = "/logout",produces = "text/plain;charset=utf-8")
    public String logout(HttpSession session){
        //刪除session中的數(shù)據(jù)
        session.invalidate();
        return "退出成功";
    }
    /**
     * 判斷session中是否有數(shù)據(jù)
     * @param session
     * @return
     */
    @GetMapping(value = "/r/r1",produces = "text/plain;charset=utf-8")
    public String r1(HttpSession session){
        String fullname = null;
        //到session中獲取數(shù)據(jù)
        Object attribute = session.getAttribute(UserDto.SESSION_USER_KEY);
        if (attribute==null){
            fullname="匿名";
        }else {
            fullname=((UserDto)attribute).getFullname();
        }
        return fullname+"訪問(wèn)r1";
    }

    @GetMapping(value = "/r/r2",produces = "text/plain;charset=utf-8")
    public String r2(HttpSession session){
        String fullname = null;
        //到session中獲取數(shù)據(jù)
        Object attribute = session.getAttribute(UserDto.SESSION_USER_KEY);
        if (attribute==null){
            fullname="匿名";
        }else {
            fullname=((UserDto)attribute).getFullname();
        }
        return fullname+"訪問(wèn)r2";
    }
}
  • 自定義攔截器 用于用戶的授權(quán)
//spring中的組件
@Component
//實(shí)現(xiàn) HandlerInterceptor接口
public class SimpleAuthenticationInterceptor implements HandlerInterceptor {
    //校驗(yàn)用戶請(qǐng)求的url是否在用戶的權(quán)限范圍內(nèi)
    //preHandle方法是在調(diào)用方法之前來(lái)調(diào)用這個(gè)方法
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        /**
         * 校驗(yàn)用戶請(qǐng)求的url是否有權(quán)限訪問(wèn)
         */
        //獲取session中的用戶信息
        Object attribute = request.getSession().getAttribute(UserDto.SESSION_USER_KEY);
        //校驗(yàn)是否登錄
        if (attribute==null){//代表session沒(méi)有信息 提示登錄
            writContext(response,"請(qǐng)登錄");
            return false;
        }
        UserDto userDto = (UserDto) attribute;
        //獲取請(qǐng)求url
        String requestURI = request.getRequestURI();
        if (userDto.getAuthorities().contains("p1")&&requestURI.contains("r/r1")){
            return true;
        }
        if (userDto.getAuthorities().contains("p2")&&requestURI.contains("r/r2")){
            return true;
        }
        writContext(response,"沒(méi)有權(quán)限訪問(wèn)");
        return false;
    }

    //響應(yīng)信息給前端
    private void writContext(HttpServletResponse response, String msg) throws IOException {
        //誰(shuí)知響應(yīng)格式
        response.setContentType("text/application;charset=utf-8");
        PrintWriter writer = response.getWriter();
        //向前端返回?cái)?shù)據(jù)
        writer.print(msg);
        writer.close();
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容