spring security4 详细配置

在使用Spring Security之前首先要有个spring的web项目,这里不再多说。

第一步:添加spring security依赖


<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>4.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>4.0.2.RELEASE</version>
</dependency>

第二步:添加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>

第三步:配置security的配置文件


这里是写死的两个用户名密码,下面注释掉的是从数据库取数据验证的

<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"
             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">

    <http use-expressions="false">
        <!-- 登录页面不需要控制权限 -->
        <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
        <!-- 访问其他所有页面都需要有USER权限 -->
        <intercept-url pattern="/**" access="ROLE_USER" />
        <!-- 配置登录页面地址login-page、登录失败后的跳转地址authentication-failure-url -->
        <form-login login-page='/login.jsp' authentication-failure-url='/login.jsp?error' default-target-url="/index.jsp" />
        <!-- 登出功能 -->
        <logout />
        <csrf disabled="true" />

        <!-- 指定自定义过滤器 -->
        <custom-filter ref="authenticationFilter" before="FORM_LOGIN_FILTER" />

    </http>


    <!-- 自定义过滤器 -->
    <beans:bean id="authenticationFilter" class="com.snow.security4.controller.TestLoginFilter">
        <beans:property name="filterProcessesUrl" value="/login" />
        <beans:property name="authenticationManager" ref="authenticationManager" />
    </beans:bean>



    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <!-- 这里创建两个用户,可以通过用户名密码登录 -->
                <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
                <user name="bob" password="bobspassword" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>


 <!-- 配置数据源 -->
    <beans:bean id="dataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <beans:property name="url" value="jdbc:mysql://localhost:3306/CTB?serverTimezone=GMT" />
        <beans:property name="username" value="mzh" />
        <beans:property name="password" value="mzh" />
    </beans:bean>

</beans:beans>

经过上面的配置,启动服务器,用浏览器打开这个Web应用的任意一个页面,都会跳转到一个登录页,这个登录页面是Spring Security自动生成的。

这里写图片描述

输入写死的那俩用户名密码即可登录成功。

TestLoginFilter类是个过滤器,如上配置,实在每次spring security做验证之前都会先经过,这个过滤器。也可以改成after,就是验证之后经过。

package com.snow.security4.controller;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by mazhenhua on 2017/3/20.
 */
public class TestLoginFilter extends UsernamePasswordAuthenticationFilter {


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        System.out.println("就是你了");

        return super.attemptAuthentication(request, response);
    }
}

第四步:连数据库做验证


一个比较简单的方法是:

 <authentication-manager>
        <authentication-provider user-service-ref='userDetailsService' />
    </authentication-manager>
    <beans:bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
        <beans:property name="dataSource" ref="dataSource"/>
        <beans:property name="usersByUsernameQuery" value="SELECT username, password, true FROM ctb.user_info WHERE username = ?" />
        <beans:property name="authoritiesByUsernameQuery" value="SELECT username, usertype true FROM ctb.user_info WHERE username = ?;" />
    </beans:bean>

直接把读密码和用户民权限的sql,丢进来,会直接读的,

复杂一点的验证,需要实现一个接口org.springframework.security.core.userdetails.UserDetailsService

public class UserDetailsServiceImpl implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 以下可以替换成用其他方式获取用户信息
        if(username.equals("xxg")) {
            Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
            SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); 
            auths.add(authority);
            User user = new User(username, "123456", auths);
            return user;
        } else {
            throw new UsernameNotFoundException("用户不存在");
        }
    }
}

然后再配置文件中配

<authentication-manager>
    <authentication-provider user-service-ref='userDetailsService' />
</authentication-manager>
<beans:bean id="userDetailsService" class="com.snow.security4.controller.UserDetailsServiceImpl" />

第五步:密码加密


明文保存密码通常是不安全的,在Spring Security中可以配置密码的加密方法。下面以MD5加密密码为例。

针对密码加密,Spring Security提供了org.springframework.security.crypto.password.PasswordEncoder接口。我们需要实现PasswordEncoder接口,实现我们自定义的加密方法,这样Spring Security在接收到用户登录请求后,会调用这个实现类,从而判断密码是否正确:

public class PasswordEncoderImpl implements PasswordEncoder {

    @Override
    public String encode(CharSequence rawPassword) {
        try {
            // MD5加密密码
            return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return encode(rawPassword).equals(encodedPassword);
    }
}

配置文件:

<authentication-manager>
    <authentication-provider>
        <password-encoder ref="passwordEncoder" />
    </authentication-provider>
</authentication-manager>
<beans:bean id="passwordEncoder" class="com.snow.security4.controller.PasswordEncoderImpl" />

第六步:Remember Me


目前很多网站登录时都有“记住我”、“下次自动登录”这样的chechbox,用户登录成功后下次再访问网站就不需要重复登录,对用户来说非常方便。这个功能在Spring Security中实现起来非常简单。

首先,你需要在html上写一个checkbox,name为 remember-me

<input type="checkbox" id="keep-login" name="remember-me"><label for="keep-login">Remember Me</label>

然后在Spring Security配置文件中加入:

<http use-expressions="false">
    // 如果之前配置http标签,这里只将remember-me放进去就好了
    <remember-me />
</http>

默认的Remember Me有效时间时14天,还可以通过token-validity-seconds属性自定义有效时长(单位:秒)

第七步:配置不受Spring Security管理的URL


如果Web应用中有某些URL不需要被Spring Security管理,例如一些静态文件,或者无需登录即可查看的页面,可以对这些URL配置security=”none”:

<http pattern="/resources/css/**" security="none"/>
<http pattern="/resources/images/**" security="none"/>
<http pattern="/resources/js/**" security="none"/>

第八步:禁用CSRF防御


Spring Security默认启用CSRF防御,要求每个POST请求都要都要带上CSRF token参数,如果感觉比较麻烦或者网站安全性要求不高,可以配置禁用:

<http use-expressions="false">
    // 如果之前配置http标签,这里只将remember-me放进去就好了
    <csrf disabled="true" />
</http>

第九步:获取登录用户信息


// 获取用户名
httpServletRequest.getRemoteUser();  // Servlet标准,推荐使用
SecurityContextHolder.getContext().getAuthentication().getName();

// 获取用户ROLE:
SecurityContextHolder.getContext().getAuthentication().getAuthorities();

// 判断用户是否拥有ROLE:
httpServletRequest.isUserInRole("ADMIN");
  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值