实现安全登录的两种方法

实现安全登录的两种方法登录安全——拦截器和过滤器或权限框架的使用本次我们将采用两种方法实现登录的安全性,首先介绍拦截器和过滤器。一、 过滤器和拦截器:过滤器产生的时间/开始工作的时间:进入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)


相关推荐

  • javaweb-oracle-1-57

    javaweb-oracle-1-57

  • git branch 命令查看分支、删除远程分支、本地分支

    git branch 命令查看分支、删除远程分支、本地分支gitbranch命令操作1、查看本地分支:gitbranch前面带有*号的是当前分支2、删除本地分支:gitbranch-d[branchname]提示删除了一个名为list的本地分支3、删除远程分支:gitpushorigin–delete[branchname]提示删除了一个名为201804019-test-files的…

  • C语言中open函数「建议收藏」

    C语言中open函数「建议收藏」作用:打开和创建文件。  简述:  #include  intopen(constchar*pathname,intoflag,…/*mode_tmode*/);  返回值:成功则返回文件描述符,否则返回-1  对于open函数来说,第三

  • java中的Cipher类

    java中的Cipher类随时随地阅读更多技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq666)该类位于javax.crypto包下,声明为publicclassCipherextendsObject此类为加密和解密提供密码功能。它构成了JavaCryptographicExtension…

  • AssertValid和Dump 这两个函数的作用[通俗易懂]

    AssertValid和Dump 这两个函数的作用[通俗易懂]
    AssertValid函数是用来判断表达式的合法性或正确性,如果不正确或不合法则终止程序并返回相应的提示信息 
     如AssertValid(t==0);//用来判断t是否等于0,如果t!=0则终止程序 
     Dump函数一般用来显示debug信息的,其函数中的内容一般在debug时,在debug窗口中才能看到。
    CObject::AssertValid 成员函数提供对对象内部状态的运行时检查。尽管从 CObject 派生类时不需要重写 Asse

发表回复

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

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