• SpringSecurity的简单使用


    • 导入SpringSecurity坐标

    • 在web.xml中配置过滤器

    • 编写spring-securiy配置文件

    • 编写自定义认证提供者

    • 用户新增时加密密码

    • 配置页面的login和logout

    • 获取登录用户的信息


    一.SpringSecurity简介

      Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

    如果要对Web资源进行保护,最好的办法莫过于Filter,要想对方法调用进行保护,最好的办法莫过于AOP。Spring security对Web资源的保护,就是靠Filter实现的。

    二.SpringSecurity的使用

    1.导入SpringSecurity的坐标

    <!-- SpringSecurity相关坐标 -->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>4.1.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>4.1.0.RELEASE</version>
    </dependency>

    2.在web.xml中配置过滤器

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                                 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
        <!-- 1.解决post乱码 -->
        <filter>
            <filter-name>CharacterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>utf-8</param-value>
            </init-param>
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>CharacterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <!-- 2.配置SpringMVC的前端控制器 -->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/springmvc.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
    
        <!-- 3.配置SpringSecurity的过滤器(以一当十) -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-security.xml</param-value>
        </context-param>
        <listener>
            <listener-class>
                org.springframework.web.context.ContextLoaderListener
            </listener-class>
        </listener>
        <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>
    </web-app>

    3.编写SpringSecurity的配置文件(spring-security.xml)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/security"
        xmlns:beans="http://www.springframework.org/schema/beans"
        xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        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://code.alibabatech.com/schema/dubbo 
                            http://code.alibabatech.com/schema/dubbo/dubbo.xsd
                            http://www.springframework.org/schema/security 
                            http://www.springframework.org/schema/security/spring-security.xsd">
       
        <!-- 1.配置页面的放行规则(不需要登录验证的资源) -->
        <http pattern="/*.html" security="none"></http>
        <http pattern="/css/**" security="none"></http>
        <http pattern="/img/**" security="none"></http>
        <http pattern="/js/**" security="none"></http>
        <http pattern="/plugins/**" security="none"></http>
        <http pattern="/seller/add.do" security="none"></http>
    
        <!-- 2.页面的拦截规则 -->
        <http use-expressions="false">
            <!-- 2.1当前用户必须有ROLE_USER的角色 才可以访问根目录及所属子目录的资源 -->
            <intercept-url pattern="/**" access="ROLE_USER"/>
            <!-- 2.2表单登陆,默认用户名和密码的name属性为:username和password,也可在这里配置 -->
            <form-login  login-page="/shoplogin.html"
                         default-target-url="/admin/index.html"
                         authentication-failure-url="/shoplogin.html"
                         always-use-default-target="true"/>
            <!-- 2.3关闭跨域攻击 -->
            <csrf disabled="true"/>
    
            <!-- 2.4为了解决frame框架访问问题默认是deny不允许访问,改成同一域下可以进行访问-->
            <headers>
                <frame-options policy="SAMEORIGIN"/>
            </headers>
            <!-- 2.5配置登出功能(页面注销连接到“/logout"即可完成退出到指定页面) -->
            <logout logout-success-url="/login.html"></logout>
        </http>
        
        <!-- 3.认证管理器 -->
        <authentication-manager>
            <!-- 3.1认证提供者:这里是写成固定的,也可以自定义 -->
            <authentication-provider>
                <user-service>
                    <!-- 配置当前系统的用户 authorities该用户属于哪个角色:这里写成固定的 -->
                    <user name="admin" password="123456" authorities="ROLE_USER"/>
                </user-service>
            </authentication-provider>
            <!-- 3.1认证提供者:这里是写成固定的,也可以自定义 -->
            <!-- ======================================================== -->
            <!-- 3.2通过自定义认证提供者,实现动态认证 -->
            <authentication-provider user-service-ref="userDetailService">
                <!-- 认证时,先对用户输入的密码加密再和数据库的对比 -->
                <password-encoder ref="bcryptEncoder"></password-encoder>
            </authentication-provider>    
            <!-- 3.2通过自定义认证提供者,实现动态认证 -->
        </authentication-manager>
            
        <!-- 4.认证类:配置的方式进行注入 -->
        <beans:bean id="userDetailService" class="cn.dintalk.service.UserDetailsServiceImpl">
            <beans:property name="sellerService" ref="sellerService"></beans:property>
        </beans:bean>
        
        <!-- 5.引用dubbo 服务 -->
        <dubbo:application name="dintalk-shop-web" />
        <dubbo:registry address="zookeeper://192.168.88.130:2181"/>
            <!-- 5.1配置的方式注入sellerService -->
        <dubbo:reference id="sellerService" interface=
                         "cn.dintalk.sellergoods.service.SellerService"></dubbo:reference>
        
        <!-- 6.配置密码加密方式 -->
        <beans:bean id="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></beans:bean>
    </beans:beans>

    4.编写自定义认证提供者(如需自定义)

    import org.springframework.security.core.GrantedAuthority;
    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;
    /**
     * 用户的登录认证
     * @author Mr.song
     * @date 2019/06/06 12:26
     */
    public class UserDetailsServiceImpl implements UserDetailsService {
    
        /**
         * 提供set方法以注入sellerService
         */
        private SellerService sellerService;
        public void setSellerService(SellerService sellerService) {
            this.sellerService = sellerService;
        }
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //1.根据用户名查询数据库
            TbSeller seller = sellerService.findOne(username);
            //2.判断用户是否存在
            if (seller != null){
                //3.定义集合,封装用户的角色(这里角色少,写死.也可以从数据库查询)
                List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
                grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
                if (seller.getStatus().equals("1")){//用户处于可以登录的状态
                    return new User(username,seller.getPassword(),grantedAuthorities);
                }
            }
            //3.用户不存在,认证失败
            return null;
        }
    }

    5.用户新增时加密密码(如需加密)

    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    /**
    * 增加
    * @param seller
    * @return
    */
    @RequestMapping("/add")
    public Result add(@RequestBody TbSeller seller){
        try {
            //添加时进行密码的加密,登录时配置同样的加密器即可
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            String newPws = passwordEncoder.encode(seller.getPassword());
            seller.setPassword(newPws);
            sellerService.add(seller);
            return new Result(true, "增加成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, "增加失败");
        }
    }

    6.配置页面的login和logout

    <!-- 1.login的配置要点:默认,登录框的name属性分别为username和password(也可在配置中修改)
        登录表单提交方式为post,登录链接为:/login-->
    <form method="post" id="loginform" action="/login">
        <input name="username" type="text" placeholder="邮箱/用户名/手机号">
        <input name="password" type="password" placeholder="请输入密码">
        <a onclick="document:loginform.submit()" target="_blank">&nbsp;&nbsp;</a>
    </form>
    
    <!-- 2.logout的配置要点:默认,退出链接为:/logout即可 -->
    <a href="/logout" >注销</a>

    7.获取登录用户的信息

    import org.springframework.security.core.context.SecurityContextHolder;
    ...
    /**
     * 获取用户登录名进行展示
     * @return
     */
    @RequestMapping("/showName")
    public Map showName(){
        //1.从认证处取得登录信息(除了username还可获取其他信息)
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        //2.构建Map并返回
        HashMap<String, String> map = new HashMap<>();
        map.put("name",name);
        return map;
    }

    关注微信公众号,随时随地学习

  • 相关阅读:
    20160421
    20160420笔记
    第一个随笔
    搬家
    OO第十五次作业
    OO第三次博客作业
    OO5-7次作业总结
    从入门到不放弃——OO第一次作业总结
    第八次团队作业——系统设计和任务分配
    第七次作业-团队选题报告和需求规格说明书
  • 原文地址:https://www.cnblogs.com/dintalk/p/10987835.html
Copyright © 2020-2023  润新知