• 初探SpringSecurity


    一、导入核心jar包

    <dependency>
              <groupId>org.springframework.security</groupId>
              <artifactId>spring-security-core</artifactId>
    </dependency>
      
    <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>org.springframework.security</groupId>
          <artifactId>spring-security-taglibs</artifactId>
     </dependency>

    二、在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>

    三、新建权限的配置文件 applicationContext-security.xml

    1.头文件如下

    <?xml version="1.0" encoding="UTF-8"?>
    <!--suppress ALL -->
    <beans:beans xmlns="http://www.springframework.org/schema/security"
                 xmlns:beans="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:context="http://www.springframework.org/schema/context"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.0.xsd
            http://www.springframework.org/schema/security
            http://www.springframework.org/schema/security/spring-security.xsd">       
     </beans:beans>   

    2.基本概念

    权限=认证和授权

    认证=校验用户名或者密码的有效性 密码是加密  密码 加密+加盐

    授权=为授权通过的用户设置角色或者资源  ROLE_为前缀都是角色   

    权限最基本的表  4张表和5张表

     

    3.开始配置applicationContext-security.xml

    <http pattern="/login.jsp" security="none"/>  #登录页面
    <http pattern="/user/doValidateCode" security="none"/> #验证码的方法
    <http pattern="/static/**" security="none"/>  #所有的静态资源
    #表示哪些资源不需要做拦截

    4.规定所有的资源都需要具有USER角色才能访问  ROLE_USER 

    <http auto-config="true">    
    <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
    </http>

    5.在http标签里面我们可以配置登录的信息

    <http auto-config="true">    
    <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
    
       <form-login
                    login-page="/login.jsp"  #登录的页面
                    login-processing-url="/user/doLogin" #登录页面的请求地址
                    default-target-url="index.jsp"  #默认的页面
                    username-parameter="username"  #登录页面的用户名的参数
                    password-parameter="password"  #登录页面的密码的参数
                    authentication-success-handler-ref="successHandler" #登录页面成功之后跳转的类
                    authentication-failure-url="/login.jsp" #失败之后跳转的页面
            />
        
        #invalidate-session  清除session
        #logout-url    退出的方法
         <logout invalidate-session="true" logout-url="/user/doLogOut"></logout>  
        
           
        #在测试阶段 我们把它关闭 一般在真实下环境 我们要把防止CSRF跨站攻击给打开
        <http:csrf disabled="true"></http:csrf>
        
        #防止iframe攻击 一般把它关闭掉
        <http:headers disabled="true" defaults-disabled="true"></http:headers>
        
        #定义好/user/doLogOut地址 只要请求该地址 就自动跳转到首页 并且清空Session
        <logout invalidate-session="true" logout-url="/user/doLogOut"></logout>
     </http>
    
    
    
    
      #认证是我们代码的核心 所有的认证都是由userService这个Bean来实现的
    <beans:bean id="cryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></beans:bean>
      
    
    <authentication-manager>
        <authentication-provider user-service-ref="userService">
            <password-encoder ref="cryptPasswordEncoder"></password-encoder>
        </authentication-provider>
      </authentication-manager>

    配置好的applicationContext-security.xml如下

    <?xml version="1.0" encoding="UTF-8"?>
    <!--suppress ALL -->
    <beans:beans xmlns="http://www.springframework.org/schema/security"
                 xmlns:beans="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:context="http://www.springframework.org/schema/context"
                 xmlns:http="http://www.springframework.org/schema/security"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.0.xsd
            http://www.springframework.org/schema/security
            http://www.springframework.org/schema/security/spring-security.xsd">
    
    
      <http pattern="/static/**"  security="none"></http>
      <http pattern="/login.jsp"  security="none"></http>
    
    
      <http auto-config="true"  >
        <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
    
    
        <form-login
                login-page="/login.jsp"
                login-processing-url="/user/doLogin"
                username-parameter="username"
                password-parameter="password"
                authentication-success-handler-ref="successHandler"
                default-target-url="index.jsp"
                authentication-failure-url="/login.jsp"
        ></form-login>
    
    <!--    <http:access-denied-handler error-page="/error/403.jsp"></http:access-denied-handler>-->
    
       <http:csrf disabled="true"></http:csrf>
    
        <http:headers disabled="true" defaults-disabled="true"></http:headers>
    
        <logout invalidate-session="true" logout-url="/user/doLogOut"></logout>
     </http>
    
    
    
    
    <beans:bean id="cryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></beans:bean>
    
    
      <authentication-manager>
        <authentication-provider user-service-ref="userService">
         <password-encoder ref="cryptPasswordEncoder"></password-encoder>
        </authentication-provider>
      </authentication-manager>
    </beans:beans>

    四、Spring配置文件applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="
                        http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
                        http://www.springframework.org/schema/aop
                        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <context:annotation-config />
    
        <context:component-scan base-package="com">
           <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
           <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController"/>
        </context:component-scan>
    
        <bean id="annotationPropertyConfigurerRedis"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="order" value="1" />
            <property name="ignoreUnresolvablePlaceholders" value="true" />
            <property name="locations">
                <list>
                     <value>classpath:jdbc.properties</value>
    
                </list>
            </property>
        </bean>
    
    
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
              init-method="init" destroy-method="close">
            <property name="driverClassName" value="${db.dirverClass}"></property>
            <property name="url" value="${db.url}" />
            <property name="username" value="${db.username}" />
            <property name="password" value="${db.password}" />
    
            <property name="initialSize" value="1" />
            <property name="minIdle" value="1" />
            <property name="maxActive" value="20" />
    
            <property name="maxWait" value="60000" />
    
            <property name="timeBetweenEvictionRunsMillis" value="60000" />
    
            <property name="minEvictableIdleTimeMillis" value="300000" />
    
            <property name="validationQuery" value="SELECT 1" />
            <property name="testWhileIdle" value="true" />
            <property name="testOnBorrow" value="false" />
            <property name="testOnReturn" value="false" />
    
            <property name="poolPreparedStatements" value="true" />
            <property name="maxPoolPreparedStatementPerConnectionSize"
                      value="20" />
    
            <property name="filters" value="stat" />
        </bean>
    
    
        <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    
        </bean>
    
        <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.blb.mapper"></property>
        </bean>
    
    
    </beans>

    五、SpringMVC配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:http="http://www.springframework.org/schema/security"
           xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="
                        http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
                         http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security.xsd
                        http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <context:annotation-config />
    
        <context:component-scan base-package="com" use-default-filters="true">
            <context:include-filter  type="annotation" expression="org.springframework.stereotype.Controller"/>
            <context:include-filter  type="annotation" expression="org.springframework.web.bind.annotation.RestController"/>
        </context:component-scan>
    
    
        <bean
           class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/" ></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    
    
        <mvc:annotation-driven/>
    
    
    
    
    
        <http:global-method-security secured-annotations="enabled"  pre-post-annotations="enabled"></http:global-method-security>
    
         <mvc:default-servlet-handler></mvc:default-servlet-handler>
    
    
    
    
    </beans>

    六、Mybatis配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
    
    </configuration>

    七、自定义登录成功后返回的对象

    User对象自动存放到UsernamePasswordAuthenticationToken

    package com.blb.vo;
    
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.User;
    
    import java.util.Collection;
    
    /**
     * @author Administrator
     * @date 2020/6/15
     */
    public class LoginUserVO extends User {
        private String welcome;
    
    
        public LoginUserVO(String username, String password, Collection<? extends GrantedAuthority> authorities) {
            super(username, password, authorities);
        }
    
        public LoginUserVO(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
            super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
        }
    
        public LoginUserVO(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities,String welcome) {
            super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
            this.welcome=welcome;
        }
    
        public String getWelcome() {
            return welcome;
        }
    
        public void setWelcome(String welcome) {
            this.welcome = welcome;
        }
    }

    八、编写登录认证、授权的类

    该类需要实现UserDetailsService

    package com.blb.service;
    
    import com.blb.vo.LoginUserVO;
    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 org.springframework.stereotype.Service;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author Administrator
     * @date 2020/6/15
     */
    @Service
    public class UserService implements UserDetailsService {
    
        //认证
        //授权 角色 资源
        //都放在一个方法里面去
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            if(username.equals("zhangsan"))
            {
    
                List list=new ArrayList<>();
                SimpleGrantedAuthority simpleGrantedAuthority=new SimpleGrantedAuthority("ROLE_USER");
                //SimpleGrantedAuthority simpleGrantedAuthority=new SimpleGrantedAuthority("ROLE_ADMIN");
                SimpleGrantedAuthority simpleGrantedAuthority2=new SimpleGrantedAuthority("USER_DROP");
                list.add(simpleGrantedAuthority);
                list.add(simpleGrantedAuthority2);
                //用户可能不可用
                //用户可能被锁定
                //用户可能被禁用
    
    
               // return  new User(username,"123456",list);
              return new LoginUserVO(username,"$2a$10$VFZXFyQShsKv/aAZxtnXlOKBg2Yczw.0CI5fwnc4QsiGWk8ryKahy",true,true,true,true,list);
            }
            return null;
        }
    }

    九、编写认证成功后的类

    package com.blb.handler;
    
    import com.blb.vo.LoginUserVO;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * @author Administrator
     * @date 2020/6/15
     */
    @Component
    public class SuccessHandler implements AuthenticationSuccessHandler{
        @Override
        public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
    
            LoginUserVO userVO=(LoginUserVO) authentication.getPrincipal();
            userVO.setWelcome("大家听明白没有");
    
            httpServletRequest.setAttribute("menu","我是一个寂寞的菜单");
            httpServletRequest.getRequestDispatcher("/index.jsp").forward(httpServletRequest,httpServletResponse);
    
    }
    }

    十、准备好一个常量来判断登录后返回的信息

    package com.blb.Contant;
    
    import org.springframework.security.authentication.InternalAuthenticationServiceException;
    import org.springframework.security.core.userdetails.UserDetailsService;
    
    /**
     * @author Administrator
     * @date 2020/6/15
     */
    public class AuthContant {
    
        public static final String InternalAuthenticationServiceException ="org.springframework.security.authentication.InternalAuthenticationServiceException: UserDetailsService returned null, which is an interface contract violation";
    }

    十一、在jsp页面判断

    <c:if test="${sessionScope.SPRING_SECURITY_LAST_EXCEPTION eq AuthContant.InternalAuthenticationServiceException}">
          用户名不存在
    </c:if>

    常见的错误异常如下

    用户名不存在:InternalAuthenticationServiceException;
    密码错误:BadCredentialException;
    帐户被锁:LockedException;
    帐户未启动:DisabledException;
    密码过期:CredentialExpiredException;等等!

    十二、jsp页面处理权限问题(选择性显示与隐藏页面的功能)

    引入头文件

    <%@taglib prefix="secuity" uri="http://www.springframework.org/security/tags" %>

    判断是否有USER_ADD的权限

     <security:authorize access="hasAuthority('USER_ADD')">
            <button class="layui-btn" lay-event="isAll">全选</button>
     </security:authorize>

    判断是否ROLE_USER的角色

    授权的时候要加上前缀

    判断的时候不需要加前缀

    <security:authorize access="hasRole('USER')">
       <button class="layui-btn" lay-event="save">新增</button>
    </security:authorize>

    十三、编写带有权限的Controller方法

    package com.blb.controller;
    
    import org.springframework.security.access.annotation.Secured;
    import org.springframework.security.access.prepost.PostAuthorize;
    import org.springframework.security.access.prepost.PreAuthorize;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /**
     * @author Administrator
     * @date 2020/6/15
     */
    @Controller
    @RequestMapping("admin")
    public class UserController {
    
       @RequestMapping("add")
       @PreAuthorize("hasAuthority('USER_ADD')")
       public String  add()
       {
           System.out.println("我是添加页面");
           return "user/add";
       }
    
    }

    @PreAuthorize("hasAuthority('USER_ADD')")使用该注解的前提是下图的配置必须在springmvc的配置文件中

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

    该注解其它的用法:

    @PreAuthorize("hasRole('ROLE_ADMIN')")  必须有XXX角色才能访问
    @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
    @PreAuthorize("#id<10")  #id 表示方法的参数就是id
    @PreAuthorize("principal.username.equals(#username)")

    如果不想使用默认的注解方法,其它例如JSR250

    https://www.cnblogs.com/fenglan/p/5913481.html

    添加jar包

    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>jsr250-api</artifactId>
        <version>1.0</version>
    </dependency>
    @RolesAllowed({"ROLE_USER", "ROLE_ADMIN"}) 必须要有XXX的角色
    @PermitAll() 所有人都可以访问该方法
    @DenyAll() 谁都不能访问该方法
    @Secured("ROLE_ADMIN")  必须要有XXX角色才能访问

    十四、在页面上,我们可以使用security:authentication 该标签就表示token,来获取token中的信息

    <security:authentication property="principal.username"></security:authentication>
  • 相关阅读:
    结对编程的理解
    第1章 python基础
    第 3 章 前端基础之JavaScript
    第1 章 mysql数据库之简单的DDL和DML sql语句
    第 1 章 前端之html
    第 13 章 python并发编程之io模型
    第 2 章 前端基础之CSS
    第 4 章 前端基础之jquery
    第 11 章 python线程与多线程
    注册表 SAM
  • 原文地址:https://www.cnblogs.com/theyang/p/13143716.html
Copyright © 2020-2023  润新知