SpringSecurity权限框架的使用

1.权限框架的介绍

springSecurity权限框架两个功能
  认证 未登录不允许访问
  授权 登录后权限不足不允许访问

2.使用

1.引入依赖
 <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring‐security‐web</artifactId>
        <version>5.0.1.RELEASE</version>
</dependency>
2.配置web.xml
1.spring的监听器 加载权限框架的配置文件 2.security权限框架的过滤器执行链
<!--监听器-->
<listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:security.xml</param-value>
</context-param>

<!--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.配置security框架的xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:security="http://www.springframework.org/schema/security"
      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://www.springframework.org/schema/security          
   http://www.springframework.org/schema/security/spring-security.xsd">

   <!--
       配置拦截的规则
       auto-config="使用自带的页面"
       use-expressions="是否使用spel表达式",如果使用表达式:hasRole('ROLE_USER')

       hasRole([role])
       当前用户是否拥有指定角色。

       hasAnyRole([role1,role2])
       多个角色是一个以逗号进行分隔的字符串。如果当前用户拥有指定角色中的任意一个则返回true。

       hasAuthority([auth])
       等同于hasRole

       hasAnyAuthority([auth1,auth2])
       等同于hasAnyRole

       Principle
       代表当前用户的principle对象

       authentication
       直接从SecurityContext获取的当前Authentication对象

       permitAll
       总是返回true,表示允许所有的

       denyAll
       总是返回false,表示拒绝所有的

       isAnonymous()
       当前用户是否是一个匿名用户

       isRememberMe()
       表示当前用户是否是通过Remember-Me自动登录的

       isAuthenticated()
       表示当前用户是否已经登录认证成功了。

       isFullyAuthenticated()
       如果当前用户既不是一个匿名用户,同时又不是通过Remember-Me自动登录的,则返回true。
   -->

   <!--配置放行的页面资源-->
   <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="/pages/**" security="none"/>
   <security:http pattern="/plugins/**" security="none"/>

   <!--针对拦截的规则配置
   auto-config="true 表示应用默认的框架配置
   use-expressions="false" 关闭权限框架的表达式
   intercept-url  拦截规则 pattern="/** 拦截所有
   access="ROLE_USER"  必须拥有ROLE_USER角色的用户可以访问
   -->
   <!--权限的控制需要开启对权限框架表达式的支持-->
   <!-- <security:http auto-config="true" use-expressions="false">
        <security:intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_PRODUCT,ROLE_ORDER"/>-->
   <security:http auto-config="true" use-expressions="true">
       <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_ADMIN','ROLE_PRODUCT','ROLE_ORDER')"/>
       <!--添加节点配置自定义的页面
       login-page 自定义的登录页面
       login-processing-url 表单请求登录的url地址
       default-target-url 登录成功的地址
       authentication-failure-url 登录失败的页面
       -->
       <security:form-login login-page="/login.jsp"
                            login-processing-url="/login"
                            default-target-url="/index.jsp"
                            authentication-failure-url="/failer.jsp"
       />
       <!--配置权限不足的页面-->
       <security:access-denied-handler error-page="/403.jsp"/>

       <!--关闭跨域攻击的拦截-->
       <security:csrf disabled="true"/>

       <!--
           配置退出的功能,securiry框架内部提供session
           invalidate-session="true" 清除session中的数据
           logout-url="/logout"    退出功能的请求路径
           logout-success-url="/login.jsp" 退出成功后跳转的页面
       -->
       <security:logout
               invalidate-session="true"
               logout-url="/logout"
               logout-success-url="/login.jsp"
       />

   </security:http>

   <!--验证节点的配置-->
   <!-- 在内存中临时提供用户名和密码的数据 -->
   <security:authentication-manager>
     
       <!--user-service-ref 表示应用一个自定义的用户业务类 -->
       <!-- 提供服务类,去数据库查询用户名和密码 -->
       <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"/>
</beans>
4.用真实用户验证用户登录

1.login.jsp页面

<form action="${pageContext.request.contextPath}/login"    method="post">

2.退出

<a href="${pageContext.request.contextPath}/logout"
  class="btn btn-default btn-flat">注销</a>

3.UserService接口需要继承框架的UserDetailsService的方法

public interface ISysUserService extends UserDetailsService {

}

4.UserServiceImpl

@Service("userService")
public class SysUserServiceImpl implements ISysUserService {
   /**
    * 该方法是认证的方法
    * 先编写一个默认的认证代码
    * 参数就是表单提交的用户名
    */
   @Override
   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
 @Autowired
    private SysDao dao;
       // 获取用户真实角色验证登录
       SysUser sysUser = dao.findByName(username);
       // 真的权限
       List<GrantedAuthority> authorities = new ArrayList<>();
       // todo 错误写法!不要查询所有权限 要查询该用户具有权限
       // List<Role> roleList = roleDao.findAllRole();
       List<Role> roleList = sysUser.getRoles();
       // 判断所有权限是否为空
       if (roleList != null && roleList.size() > 0) {
           for (Role role : roleList) {
               // 不为空 传入角色
               authorities.add(new SimpleGrantedAuthority(role.getRoleName().toUpperCase()));
           }
       }

       // 给一个假的权限authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN "));

       // 创建用户
       // 修改登录的方法,把{noop}代码去掉,表示采用加密方式登录
       //User user = new User(username, "{noop}" + sysUser.getPassword(), authorities);
       // User user = new User(username, sysUser.getPassword(), authorities);

       /*修改userService实现类 在登录时候根据数据库状态赋予User对象的状态验证属性
        中间的4个boolean属性含义为:默认都是true 代表可用
       账号是否可用
       账号是否过期
       密码是否过期
       账号是否锁定
       有一个为FALSE则登录失败*/
       User user = new User(username, sysUser.getPassword(), sysUser.getStatus() == 1 ? true : false, true, true, true, authorities);

       return user;
   }
}

5.获取用户名

//1.分析用户存储位置为securityContext---authentication---principal对象中
//后台获取权限框架存储的用户对象
SecurityContext context = SecurityContextHolder.getContext();
User user = (User) context.getAuthentication().getPrincipal();
System.out.println(user.getUsername());
<!--2.jsp页面获取方式 原始session域中获取 -->
${SPRING_SECURITY_CONTEXT.authentication.principal.username}
<!--导入标签
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
-->
<!--通过权限框架标签获取-->
<security:authentication property="principal.username"/>

二、授权功能

在JSP页面中使用security:authorize标签,可以控制菜单是否显示。

    security:authorize标签的access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"

因为需要编写表达式,要把表达式设置成true
<!--权限的控制需要开启对权限框架表达式的支持-->
<security:http auto-config="true" use-expressions="true">
   <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_ADMIN','ROLE_PRODUCT','ROLE_ORDER')"/>`
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %> 
<!--只有具有ROLE_USER和ROLE_ADMIN权限才会显示这个菜单 -->
<security:authorize access="hasAnyRole('ROLE_USER','ROLE_ADMIN')">
 <li id="system-setting">
 <a href="${pageContext.request.contextPath}/product/findByPageHelper">
 <i class="fa fa-circle-o"></i> 产品管理
 </a>
 </li>
</security:authorize>

<security:authorize access="hasAnyRole('ROLE_USER','ROLE_ADMIN')">
 <li id="system-setting"><a
 href="${pageContext.request.contextPath}/order/findAll">
 <i class="fa fa-circle-o"></i> 订单管理
 </a>
 </li>
</security:authorize>
3.在服务器端控制权限(必须的!)

3.1在springmvc.xml配置文件中配置

<!-- 开启AOP的支持 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>

JSR-250注解方式权限拦截

    在pom.xml文件中引入坐标

    <dependency>
         <groupId>javax.annotation</groupId>
         <artifactId>jsr250-api</artifactId>
         <version>1.0</version>
     </dependency>

    在spring-security.xml配置文件中开启JSR-250的注解支持

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

    在Controller的类或者方法上添加注解

    @RolesAllowed("ROLE_ADMIN")
    public class RoleController {

    配置没有权限的提示页面

    <security:access-denied-handler error-page="/403.jsp"/>

security注解方式权限拦截

    在spring-security.xml配置文件中开启注解支持

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

    在Controller类或者方法添加注解

    @Secured("ROLE_ADMIN")
    public class RoleController

Spring表达式的方式

    在spring-security.xml配置文件中开启注解支持

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

    在Controller类或者方法添加注解

    @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    public class RoleController {}

发表评论