下面是“Java web含验证码及权限登录实例代码”的完整攻略:
准备工作
在开始编写代码前,我们需要准备一些工作:
- 确保已经安装好Java开发环境,并且熟悉Java web开发基础知识。
- 安装一个Web服务器,比如Tomcat。
- 准备好一个关系数据库,比如MySQL。
功能概述
我们这里实现的是一个带有验证码和权限登录控制的Java Web应用。功能包括:
- 用户注册
- 用户登录
- 权限控制
- 验证码生成和校验
技术选型
我们使用以下技术来实现这个应用:
- Spring Framework: 用于依赖注入、控制反转和AOP等功能。
- Spring MVC: 基于Spring Framework的MVC框架。
- Spring Security: 提供权限控制和安全性的框架。
- MyBatis: 用于操作关系数据库。
- Maven: 用于管理项目依赖。
详细步骤
下面是具体的步骤:
1. 创建Maven项目
首先,我们需要创建一个Maven项目。在项目根目录下,执行以下命令:
mvn archetype:generate -DgroupId=com.example -DartifactId=demo -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
该命令会创建一个名为demo的Maven项目。
2. 添加依赖
接下来,我们需要添加依赖。在pom.xml文件中添加以下依赖:
<dependencies>
<!-- Spring Framework -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.4.1</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- Servlet and JSP API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- jBCrypt for password hashing -->
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<!-- Commons Lang for generating random strings -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- Google Guava for generating random numbers -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.0-jre</version>
</dependency>
</dependencies>
这里我们使用了Spring Framework和Spring Security来实现权限控制,MyBatis来操作关系数据库,MySQL作为关系数据库,jBCrypt用于密码哈希,Commons Lang和Google Guava用于生成随机字符串和数字等。
3. 配置Spring和MyBatis
下一步,我们需要添加Spring和MyBatis的配置文件。在src/main/resources目录下,创建一个名为applicationContext.xml的XML文件,然后添加以下内容:
<!-- 数据库连接信息 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!-- MyBatis SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:mapper/*.xml" />
</bean>
<!-- MyBatis MapperScanner -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.demo.dao" />
</bean>
这里我们配置了MySQL的连接信息,并且创建了一个SqlSessionFactoryBean和一个MapperScannerConfigurer,用于操作关系数据库。
接下来,我们需要在web.xml文件中配置Spring的DispatcherServlet,以及配置Spring Security。在src/main/webapp/WEB-INF目录下,创建一个名为spring-security.xml的XML文件,添加以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns="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">
<!-- 放行静态资源 -->
<b:http pattern="/css/**" security="none" />
<b:http pattern="/js/**" security="none" />
<b:http pattern="/images/**" security="none" />
<!-- 定义用户角色 -->
<b:authentication-manager>
<b:authentication-provider>
<b:user-service>
<!-- 定义角色 -->
<b:user name="admin" password="{bcrypt}$2a$10$B8fn7t5ZrJMGt6.8er8d1e9Uh5oK.57pn7Qd8M9.VXBKfx6nkUW6e" authorities="ROLE_ADMIN" />
<b:user name="user" password="{bcrypt}$2a$10$B8fn7t5ZrJMGt6.8er8d1e9Uh5oK.57pn7Qd8M9.VXBKfx6nkUW6e" authorities="ROLE_USER" />
</b:user-service>
</b:authentication-provider>
</b:authentication-manager>
<!-- 定义访问规则 -->
<http auto-config="true" access-denied-page="/login?error=true">
<!-- 配置登录页面 -->
<form-login login-page="/login" default-target-url="/index" authentication-failure-url="/login?error=true" />
<!-- 配置注销 -->
<logout logout-success-url="/logout" />
<!-- 定义授权规则 -->
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<intercept-url pattern="/user/**" access="ROLE_USER" />
<intercept-url pattern="/common/**" access="ROLE_ADMIN,ROLE_USER" />
<!-- 配置访问拒绝页面 -->
<access-denied-handler error-page="/403" />
</http>
</b:beans>
在这个配置文件中,我们定义了用户角色和访问规则,并且配置了登录页面、注销和访问拒绝页面。
4. 编写Java类和SQL文件
接下来,我们需要编写Java类和SQL文件。
首先,我们来编写一个User类,代表一个用户。在src/main/java/com/example/demo/entity目录下,创建一个名为User.java的类文件,添加以下内容:
package com.example.demo.entity;
public class User {
private Integer id;
private String username;
private String password;
private String role;
// getters and setters
}
这个类代表了一个用户的基本信息,包括id、username、password和role字段。
接着,我们来编写一个UserDao类,用于操作数据库中的用户表。在src/main/java/com/example/demo/dao目录下,创建一个名为UserDao.java的接口文件,添加以下内容:
package com.example.demo.dao;
import com.example.demo.entity.User;
public interface UserDao {
User getUserByUsername(String username);
int insertUser(User user);
}
这个接口包含了两个方法,一个用于根据用户名获取用户信息,一个用于插入一个用户到数据库中。
接下来,我们来实现UserDao接口。在src/main/java/com/example/demo/dao/impl目录下,创建一个名为UserDaoImpl.java的类文件,添加以下内容:
package com.example.demo.dao.impl;
import com.example.demo.dao.UserDao;
import com.example.demo.entity.User;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private SqlSessionTemplate sqlSession;
@Override
public User getUserByUsername(String username) {
return sqlSession.selectOne("UserMapper.getUserByUsername", username);
}
@Override
public int insertUser(User user) {
return sqlSession.insert("UserMapper.insertUser", user);
}
}
这个类实现了UserDao接口,并且使用了MyBatis的SqlSessionTemplate来操作数据库。
接下来,我们来编写一个UserController类,用于控制用户的注册和登录。在src/main/java/com/example/demo/controller目录下,创建一个名为UserController.java的类文件,添加以下内容:
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
public class UserController {
@Autowired
private Producer captchaProducer = null;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserService userService;
@RequestMapping(value = "/captcha.jpg", method = RequestMethod.GET)
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
String capText = captchaProducer.createText();
request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
ModelAndView mav = new ModelAndView("captcha");
mav.addObject("captchaText", capText);
return mav;
}
@GetMapping("/login")
public String login(Model model, @RequestParam(name = "error", required = false) boolean error) {
if (error) {
model.addAttribute("errorMsg", "用户名或密码错误");
}
return "login";
}
@PostMapping("/login")
public String doLogin(HttpServletRequest request, String username, String password, String captcha) {
String sessionCaptcha = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
if (!captcha.equalsIgnoreCase(sessionCaptcha)) {
return "redirect:/login?error=true";
}
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
return "redirect:/index";
}
@RequestMapping(value = "/register", method = RequestMethod.GET)
public String register(Model model) {
model.addAttribute("user", new User());
return "register";
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String doRegister(User user, String confirmPassword, String captcha, HttpServletRequest request) {
if (!captcha.equalsIgnoreCase((String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY))) {
return "redirect:/register";
}
User existUser = userService.findByUsername(user.getUsername());
if (existUser != null) {
return "redirect:/register?error=username exists";
}
if (!user.getPassword().equals(confirmPassword)) {
return "redirect:/register?error=password not match";
}
String hashedPassword = new BCryptPasswordEncoder().encode(user.getPassword());
user.setPassword(hashedPassword);
user.setRole("ROLE_USER");
userService.save(user);
return "redirect:/login";
}
@GetMapping("/index")
public String index() {
return "index";
}
@GetMapping("/admin")
public String admin() {
return "admin";
}
@GetMapping("/user")
public String user() {
return "user";
}
@RequestMapping("/403")
public String accessDenied() {
return "403";
}
}
在这个类中,我们使用了Spring Security的AuthenticationManager和Authentication对象来对用户进行认证和授权,使用了Google Kaptcha来生成和校验验证码,使用了BCryptPasswordEncoder来对用户密码进行哈希,并且编写了用户注册和登录的逻辑,实现了权限控制。
接下来,我们需要编写SQL文件,定义通过用户名获取用户信息和插入用户到数据库中的SQL。在src/main/resources/mapper目录下,创建一个名为UserMapper.xml的XML文件,添加以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="com.example.demo.dao.UserDao">
<select id="getUserByUsername" resultType="com.example.demo.entity.User"
parameterType="java.lang.String">
SELECT * FROM users
WHERE username=#{username}
</select>
<insert id="insertUser" parameterType="com.example.demo.entity.User">
INSERT INTO users(username, password, role) VALUES (
#{username}, #{password}, #{role}
)
</insert>
</mapper>
这个文件会被MyBatis自动扫描到并且用于操作数据库。
5. 编写HTML模板和CSS文件
最后,我们需要编写HTML模板和CSS文件。在src/main/webapp目录下,创建以下目录和文件:
- css/style.css: 样式文件
- images/bg.jpg: 登录页面的背景图片
- WEB-INF/views/captcha.jsp: 生成的验证码图片
- WEB-INF/views/index.jsp: 首页
- WEB-INF/views/login.jsp: 登录页面
- WEB-INF/views/register.jsp: 注册页面
- WEB-INF/views/admin.jsp: 管理员页面
- WEB-INF/views/user.jsp: 普通用户页面
- WEB-INF/views/403.jsp: 拒绝访问页面
其中,在WEB-INF/views/login.jsp页面中,我们需要添加验证码的展示:
<form action="/login" method="post">
<div>
<label>用户名:</label>
<input type="text" name="username" required>
</div>
<div>
<label>密码:</label>
<input type="password" name="password" required>
</div>
<div>
<label>验证码:</label>
<input type="text" name="captcha" required>
</div>
<div>
<img src="${pageContext.request.contextPath}/captcha.jpg" onclick="this.src='${pageContext.request.contextPath}/captcha.jpg?'+Math.random();" />
</div>
<div>
<button type="submit">登录</button>
</div>
</form>
点击
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java web含验证码及权限登录实例代码 - Python技术站