基于session的认证授权方式-SSM
具体流程:当用户登陆成功后,会在服务端将用户的相关信息保存到session中,而将发给客户端的session_id保存到cookie中,这样下次请求时带上session_id来校验服务端是否存在session数据,如果存在就校验通过,如果不存在就校验失败。当用户退出登录或session数据过期,就需要重新登录。
本案例工程使用maven进行构建,使用SpringMVC、Servlet3.0实现。
- 导入spring-webmvc,javax.servlet-api依赖
war
UTF-8
1.8
1.8
org.springframework
spring-webmvc
5.1.5.RELEASE
javax.servlet
javax.servlet-api
3.0.1
provided
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
localhost
8080
/
UTF-8
- 定义spring容器配置类
//spring容器配置 相当于applicationContext.xml
@Configuration
//组件扫描springmvc包 排除controller包
@ComponentScan(basePackages = "com.gyf.security.springmvc"
,excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class)})
public class ApplicationConfig {
//将配置文件中的配置拿到类中来配置
//配置除了Controller的其他bean,如数据库连接池,事务管理器,业务bean等
}
- 定义springmvc配置类
//servletContext配置 /相当于springvc.xml文件
//该类实现WebMvcConfigurer接口进行配置
//组件扫描springmvc包,包含Controller包
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.gyf.security.springmvc"
,includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class))
public class WebConfig implements WebMvcConfigurer {
//视图解析器
@Bean
public InternalResourceViewResolver viewResolver(){
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/view/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
//添加视图控制器
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
}
@Autowired
private SimpleAuthenticationInterceptor simpleAuthenticationInterceptor;
//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//对指定的url进行拦截
registry.addInterceptor(simpleAuthenticationInterceptor).addPathPatterns("/r/**");
}
}
- 手动加载spring配置文件
//手动加载spring配置类
//该类继承AbstractAnnotationConfigDispatcherServletInitializer,此类实现WebApplicationInitializer接口,Spring容器启动时加载WebApplicationInitializer接口的所有实现类
public class SpringApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//加载spring容器 加载ApplicationContext.xml
@Override
protected Class>[] getRootConfigClasses() {
return new Class[]{ApplicationConfig.class};
}
//servletContext 加载springmvc.xml
@Override
protected Class>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
//url-mapping
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
- 自定义认证页面 lgoin.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
用户登录
- 创建两个实体类 UserDto,AuthenticationRequest并添加get、set方法,构造方法
//用户表
public class AuthenticationRequest {
//用户名
private String username;
//密码
private String password;
}
//用户具体信息表
public class UserDto {
public static final String SESSION_USER_KEY ="_user";
//用户身份信息
private String id;
private String username;
private String password;
private String fullname;
private String mobile;
/**
* 用户的权限
*/
private Set authorities;
}
- 业务层Service 自定义认证服务用于用户的身份认证
public interface AuthenticationService {
//用户认证
UserDto authentication(AuthenticationRequest request);
}
@Service
public class AuthenticationServiceImpl implements AuthenticationService {
/**
* 用户认证
* @param request
* @return
*/
@Override
public UserDto authentication(AuthenticationRequest request) {
//校验参数是否为空
if (request==null || StringUtils.isEmpty(request.getUsername()) || StringUtils.isEmpty(request.getPassword())){
throw new RuntimeException("账号或密码为空");
}
//根据用户和密码去查询数据库 模拟数据库
UserDto userDto = this.getUserDto(request.getUsername());
//判断用户是否为空
if (userDto==null){
throw new RuntimeException("查询不到该用户");
}
//校验密码
if (!request.getPassword().equals(userDto.getPassword())){
throw new RuntimeException("密码错误");
}
//认证通过 返回用户的身份信息
return userDto;
}
//用户信息 假装到数据库获取数据
private Map map = new HashMap<>();
//代码块
{
Set authorities1 = new HashSet<>();
authorities1.add("p1");
Set authorities2 = new HashSet<>();
authorities2.add("p2");
map.put("zhangsan",new UserDto("1010","zhangsan","123456","张三","123456",authorities1));
map.put("lisi",new UserDto("1001","lisi","123","李四","789456",authorities2));
}
//根据账号查询用户信息
private UserDto getUserDto(String username){
UserDto userDto = map.get(username);
return userDto;
}
}
- 表现层Controller 仅测试用
//@Controller+@ResponseBody
@RestController
public class LoginController {
@Autowired
private AuthenticationService authenticationService;
//produces 存文本类型
@RequestMapping(value = "/login",produces = "text/plain;charset=utf-8")
public String login(AuthenticationRequest request, HttpSession httpSession){
UserDto userDto = authenticationService.authentication(request);
//将用户信息存入session
httpSession.setAttribute(UserDto.SESSION_USER_KEY,userDto);
return userDto.getUsername()+"登陆成功";
}
/**
* 删除session中的数据
* @param session
* @return
*/
@GetMapping(value = "/logout",produces = "text/plain;charset=utf-8")
public String logout(HttpSession session){
//删除session中的数据
session.invalidate();
return "退出成功";
}
/**
* 判断session中是否有数据
* @param session
* @return
*/
@GetMapping(value = "/r/r1",produces = "text/plain;charset=utf-8")
public String r1(HttpSession session){
String fullname = null;
//到session中获取数据
Object attribute = session.getAttribute(UserDto.SESSION_USER_KEY);
if (attribute==null){
fullname="匿名";
}else {
fullname=((UserDto)attribute).getFullname();
}
return fullname+"访问r1";
}
@GetMapping(value = "/r/r2",produces = "text/plain;charset=utf-8")
public String r2(HttpSession session){
String fullname = null;
//到session中获取数据
Object attribute = session.getAttribute(UserDto.SESSION_USER_KEY);
if (attribute==null){
fullname="匿名";
}else {
fullname=((UserDto)attribute).getFullname();
}
return fullname+"访问r2";
}
}
- 自定义拦截器 用于用户的授权
//spring中的组件
@Component
//实现 HandlerInterceptor接口
public class SimpleAuthenticationInterceptor implements HandlerInterceptor {
//校验用户请求的url是否在用户的权限范围内
//preHandle方法是在调用方法之前来调用这个方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
/**
* 校验用户请求的url是否有权限访问
*/
//获取session中的用户信息
Object attribute = request.getSession().getAttribute(UserDto.SESSION_USER_KEY);
//校验是否登录
if (attribute==null){//代表session没有信息 提示登录
writContext(response,"请登录");
return false;
}
UserDto userDto = (UserDto) attribute;
//获取请求url
String requestURI = request.getRequestURI();
if (userDto.getAuthorities().contains("p1")&&requestURI.contains("r/r1")){
return true;
}
if (userDto.getAuthorities().contains("p2")&&requestURI.contains("r/r2")){
return true;
}
writContext(response,"没有权限访问");
return false;
}
//响应信息给前端
private void writContext(HttpServletResponse response, String msg) throws IOException {
//谁知响应格式
response.setContentType("text/application;charset=utf-8");
PrintWriter writer = response.getWriter();
//向前端返回数据
writer.print(msg);
writer.close();
}
}