spring security添加验证码

使用spring security的时候,框架会帮我们做账户密码的验证,但是如我们需要添加一个验证码,就需要对配置文件进行修改,自己写一个方法在验证账户密码之前验证验证码。(关键是提取authenticationManager身份认证管理器,然后在身份验证之前进行验证码验证,然后再交给验证器验证账号密码)

具体操作如下:
applicationContext-security.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:security="http://www.springframework.org/schema/security"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- ########## 配置Http请求URL拦截规则 ########### -->
    <!-- 配置哪些请求URL不需要拦截,看自己需要配置 -->
    <security:http pattern="/css/**" security="none"/>
    <security:http pattern="/img/**" security="none"/>
    <security:http pattern="/js/**" security="none"/>
    <security:http pattern="/plugins/**" security="none"/>
    <security:http pattern="/*.html" security="none"/>
    <security:http pattern="*.xml" security="none"/>
    <security:http pattern="/seller/save" security="none"/>
    <security:http pattern="/user/checkCode" security="none"/>

    <!-- 配置哪些请求URL需要拦截 -->
    <!--设置认证器入口为自己的beanauthenticationEntryPoint-->
    <security:http auto-config="false" entry-point-ref="authenticationEntryPoint" use-expressions="true">
        <security:intercept-url pattern="/user/login" access="permitAll"/>
        <!-- 配置剩余的请求URL需要拦截,先登录,再获取角色 ROLE_* -->
        <security:intercept-url pattern="/**" access="hasRole('SELLER')"/>
        <!-- 配置表单登录
             登录成功后重定向
             default-target-url
             always-use-default-target
        -->

        <security:form-login
                login-page="/shoplogin.html"
                default-target-url="/admin/index.html"
                always-use-default-target="true"
                authentication-failure-url="/shoplogin.html"/>

        <!-- 关闭跨站点请求伪造 -->
        <security:csrf disabled="true"/>

        <!-- 配置请求头 -->
        <security:headers>
            <!-- 配置同一个域名下,可以访问iframe子窗口 SAMEORIGIN same origin-->
            <security:frame-options policy="SAMEORIGIN"/>
        </security:headers>

        <!-- 配置退出 -->
        <security:logout logout-url="/logout" invalidate-session="true"/>
    </security:http>

    <!-- 配置认证入口 -->
    <bean id="authenticationEntryPoint"
          class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <!-- 配置认证处理请求地址 -->
        <constructor-arg value="/user/login"/>
    </bean>


    <!-- ########## 配置身份认证管理器 ########### -->
    <!-- 配置认证管理器 -->
    <security:authentication-manager id="authenticationManager">
        <!-- 配置认证提供者 -->
        <security:authentication-provider user-service-ref="userDetailsService">
            <!-- 设置加密方式 -->
            <security:password-encoder ref="passwordEncoder"/>
        </security:authentication-provider>
    </security:authentication-manager>

    <!-- 配置密码加密 -->
    <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

    <!-- 配置服务消费者 -->
    <dubbo:application name="shop-web"/>
    <!-- 配置zookeeper注册中心,发现服务 -->
    <dubbo:registry address="zookeeper://192.168.12.131:2181"/>
    <!-- 配置引用单个服务,产生服务接口代理对象 -->
    <dubbo:reference id="sellerService" interface="service.SellerService"/>

    <!-- 配置自定义的用户认证服务 -->
    <bean id="userDetailsService" class="shop.service.UserDetailsServiceImpl">
        <property name="sellerService" ref="sellerService"/>
    </bean>


</beans>


controller中(生成验证码的方法(/user/checkCode),跟验证验证码(/user/login)的方法我写在了一起):
(提取好authenticationManager身份认证管理器之后,就可以自行认证
在控制层写一个/login方法)

/**
 * 获取登录用户名控制器
 */
@Controller
@RequestMapping("/user")
public class LoginController {

    /**
     * 注入身份认证管理器
     */
    @Autowired
    private AuthenticationManager authenticationManager;


    /**
     * 登录认证
     */
    @RequestMapping("/login")
    public void login(String username, String password, String check, HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println(check);

        if (check== null || !request.getSession().getAttribute("CHECKCODE_SERVER").toString().equals(check)) {
            response.sendRedirect("/shoplogin.html");
            return;
        }

        if (request.getMethod().equalsIgnoreCase("post")) {
            System.out.println(username + "==" + password + "==" + check);
            // 创建用户名与密码认证对象
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
            try {
                // 调用认证方法,返回认证对象
                Authentication authenticate = authenticationManager.authenticate(token);
                // 判断是否认证成功
                if (authenticate.isAuthenticated()) {
                    // 设置用户认证成功,往Session中添加认证通过信息
                    SecurityContextHolder.getContext().setAuthentication(authenticate);

                    // 重定向到登录成功页面
                    response.sendRedirect("/admin/index.html");
                    return;
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        // 重定向到登录页面
        response.sendRedirect("/shoplogin.html");
        return;
    }



    @RequestMapping("/checkCode")
    public void code(HttpServletRequest request, HttpServletResponse response) throws IOException {

        //服务器通知浏览器不要缓存

        //在内存中创建一个长80,宽30的图片,默认黑色背景
        //参数一:长
        //参数二:宽
        //参数三:颜色
        int width = 80;
        int height = 30;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        //获取画笔
        Graphics g = image.getGraphics();
        //设置画笔颜色为灰色
        g.setColor(Color.GRAY);
        //填充图片
        g.fillRect(0, 0, width, height);

        //产生4个随机验证码,12Ey
        String checkCode = getCheckCode();
        //将验证码放入HttpSession中
        request.getSession().setAttribute("CHECKCODE_SERVER", checkCode);

        //设置画笔颜色为黄色
        g.setColor(Color.YELLOW);
        //设置字体的小大
        g.setFont(new Font("黑体", Font.BOLD, 24));
        //向图片上写入验证码
        g.drawString(checkCode, 15, 25);

        //将内存中的图片输出到浏览器
        //参数一:图片对象
        //参数二:图片的格式,如PNG,JPG,GIF
        //参数三:图片输出到哪里去
        ImageIO.write(image, "PNG", response.getOutputStream());
    }

    /**
     * 产生4位随机字符串
     */
    private String getCheckCode() {
        String base = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        int size = base.length();
        Random r = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 1; i <= 4; i++) {
            //产生0到size-1的随机值
            int index = r.nextInt(size);
            //在base字符串中获取下标为index的字符
            char c = base.charAt(index);
            //将c放入到StringBuffer中去
            sb.append(c);
        }
        return sb.toString();
    }


}

前端:注册一个点击事件,用于生成新的图片验证码

 <div class="verify">
      <input name="check" type="text"
       placeholder="请输入验证码" autocomplete="off">
      <span><img src="/user/checkCode" alt=""
            onclick="changeCheckCode(this)">
     </span>
     <script type="text/javascript">
            //图片点击事件
        function changeCheckCode(img) {
             img.src = "/user/checkCode?" + new Date().getTime();
        }
     </script>
</div>
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值