实现安全登录的两种方法

实现安全登录的两种方法登录安全——拦截器和过滤器或权限框架的使用本次我们将采用两种方法实现登录的安全性,首先介绍拦截器和过滤器。一、 过滤器和拦截器:过滤器产生的时间/开始工作的时间:进入Tomcat之后,但是在进servlet之前。Interceptor进入了servlet所以拦截器拦截的是动作,而过滤器拦截的是不合理的跳转页面。1、配置和使用拦截器。<mvc:interceptors>&…

大家好,又见面了,我是你们的朋友全栈君。

登录安全——拦截器和过滤器或权限框架的使用

本次我们将采用两种方法实现登录的安全性,首先介绍拦截器和过滤器。
一、 过滤器和拦截器:
过滤器产生的时间/开始工作的时间: 进入Tomcat之后,但是在进servlet之前。Interceptor进入了servlet
所以拦截器拦截的是动作,而过滤器拦截的是不合理的跳转页面。

1、配置和使用拦截器。

<mvc:interceptors>
<mvc:interceptor>
    <!--   1.拦截所有的请求      -->
    <mvc:mapping path="/**"/>
    <!--  2.  mvc:exclude-mapping : 是一种拦截,可以放行或者对某个请求不拦截,     -->
    <mvc:exclude-mapping path="/user/doLogin.do"/>
    <!--  3. 告诉我们要用哪个拦截器      -->
    <bean class="com.zhongruan.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>

</mvc:interceptors>

解释:除了login之外的请求都不允许执行

public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //在拦截点执行前拦截,如果返回true,则不执行拦截点后的才做
    //获取session
    HttpSession session = request.getSession();
    //获取访问路径
    String uri = request.getRequestURI();
    //indexOf函数:求出字符串内路径出现的下标
    if(session.getAttribute("userInfo")!=null){
        //登录成功,不拦截
        return true;
    }else{
        //拦截成功
        response.sendRedirect(request.getContextPath()+"user/doLogin.do");
        return false;
    }

}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    //处理过程中,执行拦截
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    //执行完毕之后,返回前拦截
}

}

重写拦截点前拦截动作的函数:
如果登录成功,则证明是真正的用户,所以放弃拦截(拦截器也因此失效);如果登录失败,则重新返回登录界面,且无法输入其他动作跳转到其他界面。

2、配置和使用过滤器:

<filter>
 <filter-name>SessionFilter</filter-name>
 <filter-class>com.zhongruan.filter.LoginFilter</filter-class>
 </filter>

 <filter-mapping>
 <filter-name>SessionFilter</filter-name>
 <url-pattern>/pages/*</url-pattern>
 <url-pattern>*.jsp</url-pattern>
 </filter-mapping>

上面是指请求所有界面都要通过过滤器,filter的实现如下:

   public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    //区别:Interceptor进入了servlet,所以重写的参数时HttpServletRequest/Response
    //   Filter没有进入Servlet.ServletRequest
    //  ServletRequest是接口,HttpServletRequest是实现,这里有些方法是HttpServletRequest中独有的,例如getSession
    //所以要强制转换
    HttpServletRequest request = (HttpServletRequest)servletRequest;
    HttpServletResponse response = (HttpServletResponse)servletResponse;
    //以下类似拦截器了
    HttpSession session = request.getSession();
    if(session.getAttribute("userInfo") == null && request.getRequestURI().indexOf("/user/doLogin.do") == -1){
        // 没有登录,返回登录页面
        response.sendRedirect(request.getContextPath()+"/user/doLogin.do");
    }else{
        //已经登录了,继续请求下一步操作
        filterChain.doFilter(request,response);
    }
}

同样,过滤器使用过后就会失效,如果是真正的用户,可以访问其他界面,否则不能在登录界面访问其他界面。

结果展示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
二、 使用权限框架Spring-Security
1、首先在pom.xml文件中导入框架需要的jar包

<!--  spring.security架包      -->
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-web</artifactId>
  <version>${spring.security.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-config</artifactId>
  <version>${spring.security.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-core</artifactId>
  <version>${spring.security.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-taglibs</artifactId>
  <version>${spring.security.version}</version>
</dependency>

2、配置web.xml文件
添加如下语句:

<!--   配置 Spring-security;添加过滤器拦截所有请求  -->
 <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>

3、添加角色类:
由于验证机制是可以将用户类和管理员类区分开,登录后进入不同的界面,所以我们要增加一个角色类Role,它有三个属性:id,roleName和roleDesc,还有它们的get/set方法以及toString方法。
另外在UserInfo类中添加新的属性roleList(一个人可能对应多个角色)及其对应的方法。

4、添加Dao层:
新建一个名为“RoleDao”的接口类,并定义一个List findRoleByUserId(int userId);
方法。

 <select id="findRoleByUserId" parameterType="java.lang.Integer"        resultType="com.zhongruan.bean.Role">
    select * from tb_Role where id in(select roleId from tb_user_role    where userId=#{userId})
 </select>

可以看出,这个sql语句使用了多表查询。先在tb_user_role表中根据userid查询该用户的roleid,再在tb_Role表中查找该roleid对应的角色是什么。

5、service层:

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    // 1. 查询当前登录的用户信息
    UserInfo userInfo = userDao.doLogin(username);
    System.out.println("获得的用户线信息为:"+ userInfo);
    // 2. 查询当前的用户有多少角色
    List<Role> roleList = roleDao.findRoleByUserId(userInfo.getId());
    // 3. 需要把角色给放入用户中
    userInfo.setRoleList(roleList);

    // 4. 把查询到的User和Role数据  给到Spring-security中的内置对象User来管理
    User user = new User(userInfo.getUsername(), "{noop}" + userInfo.getPassword(), getAuthority(userInfo.getRoleList()));
    return user;

}
下面是getAuthority的代码:

private Collection<? extends GrantedAuthority> getAuthority(List<Role> roleList) {
List<SimpleGrantedAuthority> list = new ArrayList<>();
for(Role role:roleList){
    list.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleName()));
}
return list;

}
6、准备spring-security文件:

    <security:global-method-security pre-post-annotations="enabled" jsr250-annotations="enabled" secured-annotations="enabled"></security:global-method-security>

<!-- 配置不拦截的资源 -->
<security:http pattern="/login.jsp" security="none"/>
<security:http pattern="/failer.jsp" security="none"/>
<security:http pattern="/css/**" security="none"/>
<security:http pattern="/img/**" security="none"/>
<security:http pattern="/plugins/**" security="none"/>
<!--
   配置具体的规则
   auto-config="true" 不用自己编写登录的页面,框架提供默认登录页面
   use-expressions="false"    是否使用SPEL表达式(没学习过)
-->
<security:http auto-config="true" use-expressions="true">
    <!-- 配置具体的拦截的规则 pattern="请求路径的规则" access="访问系统的人,必须有ROLE_USER的角色" -->
    <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/>

    <security:form-login login-page="/login.jsp"
                         login-processing-url="/login.do"
                        default-target-url="/index.jsp"
                        authentication-failure-url="/failer.jsp"
                        authentication-success-forward-url="/pages/main.jsp"/>

    <!-- 关闭跨域请求 -->
    <security:csrf disabled="true"/>

    <!--退出并跳转到首页-->
    <security:logout invalidate-session="true" logout-url="/logout.do" logout-success-url="/login.jsp"></security:logout>
</security:http>

<!-- 切换成数据库中的用户名和密码 -->
<security:authentication-manager>
    <security:authentication-provider user-service-ref="userService">
        <!-- 配置加密的方式
        <security:password-encoder ref="passwordEncoder"/> -->
    </security:authentication-provider>
</security:authentication-manager>
<!-- 配置加密类 -->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

7、login.jsp页面:

这里直接用login.do而不是doLogin.do(之前的函数已经被注释掉了)。这个login.do的实现是在框架里写所以我们不需要管。

Aside.jsp页面:
由于登录后会在左上角显示登录用户的头像和信息以及可以进行的操作,所以需要在下拉菜单的链接加上一句<security:authentication property=“principal.username”></security:authentication>
同时加上如下代码:

<security:authorize access="hasRole('ADMIN')">
 <a
 href="${pageContext.request.contextPath}/user/findAll.do?page=1&size=5"> <i
  class="fa fa-circle-o"></i> 用户管理
</a>
 </security:authorize>

意思是只有管理员拥有“用户管理”这个选项,普通用户界面不显示。
下面是运行结果展示:

如果是输入了错误的用户名或密码:
在这里插入图片描述

如果是管理员身份成功登录:
在这里插入图片描述
如果是用户身份成功登录:
在这里插入图片描述
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/125017.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Linux生成静态库_linux生成静态库

    Linux生成静态库_linux生成静态库转自:https://blog.csdn.net/ddreaming/article/details/53096411一、动态库、静态库简介库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库.a(win系统下是lib)和动态…

  • idea2020最新版如何部署多个jdk

    idea2020最新版如何部署多个jdk

  • Python实现五子棋人机对战 | CSDN博文精选「建议收藏」

    Python实现五子棋人机对战 | CSDN博文精选「建议收藏」作者|吴小鹏来源|数据札记倌(ID:Data_Groom)五子棋是常见的一款小游戏,五子棋问题是人工智能中的一个经典问题。这篇文章主要介绍了Python版本五子棋的实现代码,大家可以做个参考,与我的傻儿子对弈一下。简述虽然计算机已经几乎激活成功教程了五子棋的取胜秘籍,甚至给出了取胜的具体方案,然而,对人来说,五子棋还是非常有玩头的。我们往往有五子棋的技巧性和全局观远远比不上象棋,围棋之类的感…

  • signature=624b2ab6df2ed724d785f89ffa77adce,CiteSeerX — Approved memorandum with signature is on file…

    signature=624b2ab6df2ed724d785f89ffa77adce,CiteSeerX — Approved memorandum with signature is on file…Abstract•BrowardPuertoRican/Hispanicstudents’meanCompositescoresmatchedorsurpassedPuertoRican/Hispanicstudentsinthestateandnationwideineveryarea.•MexicanAmerican/Chicano,Afri…

  • 多线程01_01-02

    多线程01_01-02一.基本概念程序——指令和数据的有序集合——静态Process进程——执行程序的依次执行过程——动态——系统资源分配的单位Thread线程——一个进程中可以包含多个线程(至少一个)——动态——CPU调度和执行的单位(main函数是主线程)**多线程:**有多个CPU即多核,如服务器。notes:线程是独立执行的路径程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,垃圾回收线程gcmain()称为主线程,是系统的入口,用于执行整个程序在一个进程中,如果开辟了

  • 运行时异常与非运行时异常的区别

    运行时异常与非运行时异常的区别

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号