Spering-Security

概念

比spring security更好用的权限控制框架 spring自带的权限框架_ide

概述
1、spring中提供安全认证服务的框架
	认证:验证用户密码是否正确的过程
	授权:对用户的访问资源进行控制

简单使用

目标:实现管理员和普通用户权限不同,登录后看到界面不同

  • 配置pom.xml
  • 在web.xml中配置Security的过滤器
  • 配置Spring-Security.xml

1、使用maven,在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的过滤器,会拦截所有请求
在进入服务器tomcat之后,但是在进入servlet之前生效

<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、配置Spring-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">

    <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="/index.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>
    <!--对应用户service,@Service(userService)-->
        <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"/>
    <!-- <bean id="webexpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />-->
    <!-- 提供了入门的方式,在内存中存入用户名和密码
    <security:authentication-manager>
    	<security:authentication-provider>
    		<security:user-service>
    			<security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/>
    		</security:user-service>
    	</security:authentication-provider>
    </security:authentication-manager>
    -->

</beans>

4、用户表和权限表关联(外键或新创建一张表)新建一张关联表
通过查询关联表得知用户的权限,给予不同的界面

比spring security更好用的权限控制框架 spring自带的权限框架_xml_02


比spring security更好用的权限控制框架 spring自带的权限框架_spring_03


比spring security更好用的权限控制框架 spring自带的权限框架_java_04


5、mybatis中查询语句

<select id="findRoleByUserId" parameterType="Integer" resultType="com.zhongruan.bean.Role">
        select * from tb_role where rid in (select rid from tb_user_role where uid=#{uid})
    </select>

6、在用户service中继承UserDetailsService,重写loadUserByUsername方法
登录时会调用该方法

@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名查询到当前登录用户
        UserInfo userInfo = UserInfoDao.doLogin(username);

        //根据当前用户的ID,去查询到所属的角色
        List<Role> roleList = roleDao.findRoleByUserId(userInfo.getId());

        userInfo.setRoles(roleList);
        //得到想要的信息后,就要交给Security去处理了
        User user=new User(userInfo.getUsername(),"{noop}"+userInfo.getPassword(),getAuthority(roleList));

        return user;
    }

    private Collection<? extends GrantedAuthority> getAuthority(List<Role> roleList) {
        List<SimpleGrantedAuthority> list=new ArrayList<>();
        for (Role role :
                roleList) {
                //拼接字符串,对应数据库中的ROLE_USER,ROLE_ADMAIN;Spring-Security.xml中的ROLE_USER,ROLE_ADMAIN
            list.add(new SimpleGrantedAuthority("ROLE_"+role.getRname()));
        }
        return list;
    }

在前端jsp页面中使用
需要在jsp页面头部加上:
<%@taglib prefix=“security” uri=“http://www.springframework.org/security/tags” %>

  • 获取当前登录用户信息
<div sec:authorize="isAuthenticated()">
    <p>登录名:<span sec:authentication="name"></span></p>
    <p>角色:<span sec:authentication="principal.authorities"></span></p>
    <p>Username:<span sec:authentication="principal.username"></span></p>

    <div sec:authorize="hasAuthority('ROLE_user:view:GET')">用户列表</div>
    <div sec:authorize="hasRole('user:add:POST')">添加用户</div>
    <div sec:authorize="hasAuthority('ROLE_user:update:PUT')">修改用户</div>
    <div sec:authorize="hasAuthority('ROLE_user:delete:DELETE')">删除用户</div>
</div>
  • 普通用户不能看到用户管理界面,只能管理员看得到
<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>

常用的标签库

sec:authorize 权限
sec:authentication 认证
sec:authorize-url : 不能直接使用还需额外的配置 (也不建议使用该标签,因为该标签不支持restful风格)

SecurityExpressionRoot常用的表达式

boolean hasAuthority(String authority)
boolean hasAnyAuthority(String… authorities)
boolean hasRole(String role)
hasAnyRole(String… roles)
Authentication getAuthentication()
Object getPrincipal()
boolean isAnonymous()
boolean isAuthenticated()
boolean isRememberMe()