(二)如何使用spring-security来实现用户的登录权限功能?(配合使用数据库的方式)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36520235/article/details/81839940

如何使用spring-security来实现用户的登录功能之配合使用数据库的方式

这个图大家先熟悉一下简单的过一遍,等把步骤都写完之后,后面会总结
这里写图片描述

(一)使用spring-security之前需要做的准备(基于springMVC和dubbo的项目)

这里写图片描述
1. 需要先在maven中pom文件中引入需要的spring-security的依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.pinyougou</groupId>
    <artifactId>pinyougou-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>pinyougou-shop-web</artifactId>
  <packaging>war</packaging>

  <dependencies>
    <!-- Spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
    <!-- dubbo相关 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
    </dependency>
    <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
    </dependency>
    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>        
        <scope>provided</scope>
    </dependency>
    <!-- 这个是使用SpirngSecurity的安全登录框架的依赖 -->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
    </dependency>


    <dependency>
        <groupId>com.pinyougou</groupId>
        <artifactId>pinyougou-sellergoods-interface</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
  </dependencies>


    <build>  
      <plugins>
          <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <!-- 指定端口 -->
                    <port>9102</port>
                    <!-- 请求路径 -->
                    <path>/</path>
                </configuration>
          </plugin>
      </plugins>  
    </build>



</project>

2、需要配置的web.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">  
   <!-- 解决post乱码 -->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>  
            <param-name>forceEncoding</param-name>  
            <param-value>true</param-value>  
        </init-param>  
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>   

  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/springmvc.xml</param-value>
    </init-param>
  </servlet>
  <!-- 监听整个项目的作用 -->
   <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/spring-security.xml</param-value>
     </context-param>
     <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
     </listener>
    <!-- 这个是配置的spring-security过滤链,而且这个springSecurityFilterChain名字不能变 -->
     <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>  

  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

</web-app>

(二)这一部其实就是在第(一)大步的基础上,配置spring-security中最重要的一步,这里单独作为一大步来进行解释

(1)先进行配置对静态的资源进行放行,可根据具体的业务进行特别的放行
(2)再去配置页面的拦截规则,配合着什么样的角色配什么样的权限(这个可以根据自己的业务来)
(3)配置认证管理器,也就是authentication-manager这个类,他的作用就是用来管理你所有的不同角色的用户

  1. 在这个里面还可以进行注入对用户的密码进行加密的BCrypt方式(可以自行去了解一下)
  2. 如果你想实现用户在设置密码的时候就进行加密,就直接定义加密对象,然后把用户设置的密码进行加密setter到数据库中,在认证管理器的时候,你只需要给认证管理器提供这个password-encoder参数,spring-security会帮我们自动解密
  3. 这个就是我使用的时候`
//注册用户的时候,用户自己添加设置密码的时候进行加密,然后解密的时候你配置好滴(2)步就不用管了
@RequestMapping("/add")
    public Result add(@RequestBody TbSeller seller){
        //对新增的商铺老板的密码进行加密,使用Bcrypt的加密方式
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String password = passwordEncoder.encode(seller.getPassword());
        seller.setPassword(password);

        try {
            sellerService.add(seller);
            return new Result(true, "增加成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, "增加失败");
        }
    }`

这个是service层的接口和实现类

package com.pinyougou.sellergoods.service;
import java.util.List;
import com.pinyougou.pojo.TbSeller;

import entity.PageResult;
/**
 * 服务层接口
 * @author Administrator
 *
 */
public interface SellerService {

    /**
     * 根据ID获取实体
     * @param id
     * @return
     */
    public TbSeller findOne(String id);
    }

实现类:

/**
 * 服务实现层
 * @author Administrator
 *
 */
@Service
public class SellerServiceImpl implements SellerService {

        /**
     * 根据ID获取实体
     * @param id
     * @return
     */
    @Override
    public TbSeller findOne(String id){
        return sellerMapper.selectByPrimaryKey(id);
    }
}

查询数据库的mappering文件。这里就不展示了

4、还需要在spring-security中注入解密bean类
(4)然后你需要去自定义一个类,这个类的作用就是从数据库中拿数据跟用户输入的密码进行对比(但是对比这一步不需要我们做,直接交给spring-security来做)

package com.pinyougou.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.pinyougou.pojo.TbSeller;
import com.pinyougou.sellergoods.service.SellerService;

/**认证类
 * @author user
 * 这个是专门用来动态从数据库中取数据进行和用户输入的账号和密码进行比对的
 */
public class UserDetailsServiceImpl implements UserDetailsService {

    //添加一个set方法,这里需要使用配置的方式是通过dubbo把另外的一个微服务的service工程给注入进来
    private SellerService sellerService;

    public void setSellerService(SellerService sellerService) {
        this.sellerService = sellerService;
    }


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //这个集合中装的是你的不同角色的权限分组,也就是构建一个角色列表
        List<GrantedAuthority> grantAuths = new ArrayList<GrantedAuthority>();
        //因为GrantedAuthority这个是一个接口,不能直接添加,所以需要new一个SimpleGrantedAuthority的构造器
        grantAuths.add(new SimpleGrantedAuthority("ROLE_SELLER"));
        //然后开始从数据库中去拿到数据,这里就是使用了dubbo和zookeeper来实现之间的调用
        TbSeller tbSeller = sellerService.findOne(username);
        //先判断是不是查询到了数据
        if (tbSeller!=null) {
            //然后还需要判断若果店铺的审核状态是不是通过的状态为“1”的才可以登录
            if (tbSeller.getStatus().equals("1")) {
                //表示可以访问的grantAuths
                return new User(username, tbSeller.getPassword(), grantAuths);
            }else {
                return null;
            }
        }else{
            return null;
        }
    }

}

(5)如果你有用到dubbo的话,由于你的 controller层和service层是分开的两个不同的项目,但是因为你在你自定义的类中需要调用service层来去查询数据库,所以你需要使用到dubbo和zookeeper来实现controller和service层的调用,如果你么有用到dubbo可以跳过这一步

最后成果:这是最后都配置好的spring-security.xml的文件

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    (1)<!-- 设置页面不登陆也可以访问 -->
    <http pattern="/*.html" security="none"></http>
    <http pattern="/css/**" security="none"></http>
    <http pattern="/img/**" security="none"></http>
    <http pattern="/js/**" security="none"></http>
    <http pattern="/plugins/**" security="none"></http>
    <!--这里需要加上对添加店铺信息的时候需要放行  -->
    <http pattern="/seller/add.do" security="none"></http>


    (2)<!-- 页面的拦截规则    use-expressions:是否启动SPEL表达式 默认是true -->
    <http use-expressions="false" >
        <!-- 当前用户必须有ROLE_USER的角色 才可以访问根目录及所属子目录的资源 -->
        <intercept-url pattern="/**" access="ROLE_SELLER"/>
        <!-- 开启表单登陆功能 -->
        <!-- default-target-url:这个表示登录成功默认跳转到的页面 login-page:这个表示指定的表单进行登录,不用spring-security提供的 -->
        <form-login  login-page="/shoplogin.html" default-target-url="/admin/index.html" authentication-failure-url="/pinyougou-shop-web/login.html" always-use-default-target="true"/>
        <csrf disabled="true"/>
        <headers>
            <frame-options policy="SAMEORIGIN"/>
        </headers>
        <!-- 这个是当你点击退出时候,spring-security会自动帮我们清除掉当前登录的信息和session -->
        <logout/>
    </http>


    (3)<!-- 认证管理器 -->
    <authentication-manager>
        <authentication-provider user-service-ref="UserDetailsService">
        <!-- 这个user-service其实就是相当于是你的用户源,现在改为从数据库中拿到,
        就必须得经过UserDetailsServiceImpl.java这个我们自定义的类 
        而且这个类必须需要实现UserDetailsService这个接口,下面会先把这个自定义的类注入进来-->
            <!-- <user-service>
                <user name="admin" password="123456" authorities="ROLE_ADMIN"/>
                <user name="sunwukong" password="dasheng" authorities="ROLE_ADMIN"/>
                <user name="wangwei" password="123456" authorities="ROLE_ADMIN"/>
            </user-service> -->
        <!-- 因为在用户添加的时候已经用Bcrypt加密了密码,这里需要使用spring-security来提供对应的方法来进行解密 -->
        <password-encoder ref="bcryptEncoder"></password-encoder>
        </authentication-provider>  
    </authentication-manager>

    <!-- 这个是注入认证类,也就是你自定义的那个实现 UserDetailsService这个接口的类-->
    <beans:bean id="UserDetailsService" class="com.pinyougou.service.UserDetailsServiceImpl">
        <beans:property name="sellerService" ref="sellerService"></beans:property>

    </beans:bean>

    (5)<!-- 因为在使用远程微服务的时候需要用到service层的服务工程,所以这里需要吧service层的服务工程通过dubbo来引入进来
    1.需要先在认证类中加入一个属性
     -->
     <!-- 引入dubbo服务:1、需要把dubbo有关的约束头文件也要加进来  2.然后把接口相对路径加上 3.把认证管理类的name给id的属性-->
    <dubbo:application name="pinyougou-shop-web" />
    <dubbo:registry address="zookeeper://192.168.25.132:2181"/>
    <!-- 这个可以看成是一个bean为sellerService的一个类 -->
    <dubbo:reference id="sellerService" interface="com.pinyougou.sellergoods.service.SellerService"></dubbo:reference>

    <!-- 这里需要加上从认证管理器中加入的解密bean类 -->
    <beans:bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></beans:bean>

</beans:beans>

猜你喜欢

转载自blog.csdn.net/qq_36520235/article/details/81839940