初探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>
原文地址:https://www.cnblogs.com/theyang/p/13143716.html