java 连接springmvc配置文件_SpringMVC+Shiro整合配置文件详解

今天在csxx上发现这篇文章,讲解的真的是很详细,刚好最近在使用springmvc+shiro,慢慢看。在项目中xml文件的配置是必不可少的,特别是SpringMVC框架。但是几乎所有项目的配置都是大同小异,很多人都是直接复制黏贴了事,不少人对其具体含义及用途都不甚全知。本片文章将正对项目中常用的框架SpringMVC+Shiro进行整合,并对其中关键和部分常识性问题进行注释讲解,方便在以后的项目编写中查阅和熟悉。

1、web.xml文件的配置

所有javaweb项目第一步要做的就是对web.xml文件进行配置。

<?xml  version="1.0" encoding="UTF-8"?>  

xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

contextConfigLocation

classpath*:/spring-context*.xml

org.springframework.web.util.IntrospectorCleanupListener

org.springframework.web.context.ContextLoaderListener

SpringEncodingFilter

org.springframework.web.filter.CharacterEncodingFilter

encoding

UTF-8

forceEncoding

true

SpringEncodingFilter

/*

shiroFilter

org.springframework.web.filter.DelegatingFilterProxy

targetFilterLifecycle

true

shiroFilter

/*

SpringMVC

org.springframework.web.servlet.DispatcherServlet

contextConfigLocation

classpath*:/spring-mvc*.xml

SpringMVC

/

405

/WEB-INF/405.html

404

/WEB-INF/404.jsp

500

/WEB-INF/500.jsp

java.lang.Throwable

/WEB-INF/500.jsp

2、spring-mvc.xml文件的配置

这个文件主要是对springmvc的相关配置。<?xml  version="1.0" encoding="UTF-8"?>  

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:mvc="http://www.springframework.org/schema/mvc"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.2.xsd">

WEB-INF/error_fileupload

WEB-INF/500

3、spring-context-shiro.xml文件配置

这个文件是对shiro权限框架的配置。<?xml  version="1.0" encoding="UTF-8"?>

xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-4.0.xsd"

default-lazy-init="true">

/mydemo/login=anon

/mydemo/getVerifyCodeImage=anon

/main**=authc

/user/info**=authc

/admin/listUser**=authc,perms[admin:manage]

4、MyRealm.java------自定义的Realm类package com.papio.realm;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

import org.apache.commons.lang3.builder.ToStringStyle;

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authc.SimpleAuthenticationInfo;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.authz.AuthorizationInfo;

import org.apache.shiro.authz.SimpleAuthorizationInfo;

import org.apache.shiro.realm.AuthorizingRealm;

import org.apache.shiro.session.Session;

import org.apache.shiro.subject.PrincipalCollection;

import org.apache.shiro.subject.Subject;

/**

* 自定义的指定Shiro验证用户登录的类

* @see 在本例中定义了2个用户:papio和big,papio具有admin角色和admin:manage权限,big不具有任何角色和权限

* @create

* @author

*/  public class MyRealm extends AuthorizingRealm {

/**

* 为当前登录的Subject授予角色和权限

* @see 经测试:本例中该方法的调用时机为需授权资源被访问时

* @see 经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache

* @see 个人感觉若使用了Spring3.1开始提供的ConcurrentMapCache支持,则可灵活决定是否启用AuthorizationCache

* @see 比如说这里从数据库获取权限信息时,先去访问Spring3.1提供的缓存,而不使用Shior提供的AuthorizationCache

*/

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){

//获取当前登录的用户名,等价于(String)principals.fromRealm(this.getName()).iterator().next()

String currentUsername = (String)super.getAvailablePrincipal(principals);

//      List roleList = new ArrayList();  //      List permissionList = new ArrayList();  //      //从数据库中获取当前登录用户的详细信息  //      User user = userService.getByUsername(currentUsername);  //      if(null != user){  //          //实体类User中包含有用户角色的实体类信息  //          if(null!=user.getRoles() && user.getRoles().size()>0){  //              //获取当前登录用户的角色  //              for(Role role : user.getRoles()){  //                  roleList.add(role.getName());  //                  //实体类Role中包含有角色权限的实体类信息  //                  if(null!=role.getPermissions() && role.getPermissions().size()>0){  //                      //获取权限  //                      for(Permission pmss : role.getPermissions()){  //                          if(!StringUtils.isEmpty(pmss.getPermission())){  //                              permissionList.add(pmss.getPermission());  //                          }  //                      }  //                  }  //              }  //          }  //      }else{  //          throw new AuthorizationException();  //      }  //      //为当前用户设置角色和权限  //      SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();  //      simpleAuthorInfo.addRoles(roleList);  //      simpleAuthorInfo.addStringPermissions(permissionList);

SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();

//实际中可能会像上面注释的那样从数据库取得

if(null!=currentUsername && "papio".equals(currentUsername)){

//添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色

simpleAuthorInfo.addRole("admin");

//添加权限

simpleAuthorInfo.addStringPermission("admin:manage");

System.out.println("已为用户[papio]赋予了[admin]角色和[admin:manage]权限");

return simpleAuthorInfo;

}else if(null!=currentUsername && "big".equals(currentUsername)){

System.out.println("当前用户[big]无授权");

return simpleAuthorInfo;

}

//若该方法什么都不做直接返回null的话,就会导致任何用户访问/admin/listUser.jsp时都会自动跳转到unauthorizedUrl指定的地址

//详见applicationContext.xml中的的配置

return null;

}

/**

* 验证当前登录的Subject

* @see 经测试:本例中该方法的调用时机为LoginController.login()方法中执行Subject.login()时

*/

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {

//获取基于用户名和密码的令牌

//实际上这个authcToken是从LoginController里面currentUser.login(token)传过来的

//两个token的引用都是一样的,本例中是org.apache.shiro.authc.UsernamePasswordToken@33799a1e

UsernamePasswordToken token = (UsernamePasswordToken)authcToken;

System.out.println("验证当前Subject时获取到token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));

//      User user = userService.getByUsername(token.getUsername());  //      if(null != user){  //          AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), user.getNickname());  //          this.setSession("currentUser", user);  //          return authcInfo;  //      }else{  //          return null;  //      }

//此处无需比对,比对的逻辑Shiro会做,我们只需返回一个和令牌相关的正确的验证信息

//说白了就是第一个参数填登录用户名,第二个参数填合法的登录密码(可以是从数据库中取到的,本例中为了演示就硬编码了)

//这样一来,在随后的登录页面上就只有这里指定的用户和密码才能通过验证

if("papio".equals(token.getUsername())){

AuthenticationInfo authcInfo = new SimpleAuthenticationInfo("papio", "papio", this.getName());

this.setSession("currentUser", "papio");

return authcInfo;

}else if("big".equals(token.getUsername())){

AuthenticationInfo authcInfo = new SimpleAuthenticationInfo("big", "big", this.getName());

this.setSession("currentUser", "big");

return authcInfo;

}

//没有返回登录用户名对应的SimpleAuthenticationInfo对象时,就会在LoginController中抛出UnknownAccountException异常

return null;

}

/**

* 将一些数据放到ShiroSession中,以便于其它地方使用

* @see 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到

*/

private void setSession(Object key, Object value){

Subject currentUser = SecurityUtils.getSubject();

if(null != currentUser){

Session session = currentUser.getSession();

System.out.println("Session默认超时时间为[" + session.getTimeout() + "]毫秒");

if(null != session){

session.setAttribute(key, value);

}

}

}

}

5、LoginController.java------处理用户登录package com.papio.controller;

import java.awt.Color;

import java.awt.p_w_picpath.BufferedImage;

import java.io.IOException;

import javax.p_w_picpathio.ImageIO;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

import org.apache.commons.lang3.builder.ToStringStyle;

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.ExcessiveAttemptsException;

import org.apache.shiro.authc.IncorrectCredentialsException;

import org.apache.shiro.authc.LockedAccountException;

import org.apache.shiro.authc.UnknownAccountException;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.subject.Subject;

import org.apache.shiro.web.util.WebUtils;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.servlet.view.InternalResourceViewResolver;

/**

* 本例中用到的jar文件如下

* @see aopalliance.jar

* @see commons-lang3-3.1.jar

* @see commons-logging-1.1.2.jar

* @see log4j-1.2.17.jar

* @see shiro-all-1.2.2.jar

* @see slf4j-api-1.7.5.jar

* @see slf4j-log4j12-1.7.5.jar

* @see spring-aop-3.2.4.RELEASE.jar

* @see spring-beans-3.2.4.RELEASE.jar

* @see spring-context-3.2.4.RELEASE.jar

* @see spring-core-3.2.4.RELEASE.jar

* @see spring-expression-3.2.4.RELEASE.jar

* @see spring-jdbc-3.2.4.RELEASE.jar

* @see spring-oxm-3.2.4.RELEASE.jar

* @see spring-tx-3.2.4.RELEASE.jar

* @see spring-web-3.2.4.RELEASE.jar

* @see spring-webmvc-3.2.4.RELEASE.jar

* @create Sep 30, 2013 11:10:06 PM

*/  @Controller  @RequestMapping("mydemo")  public class LoginController {

/**

* 用户登录

*/

@RequestMapping(value="/login", method=RequestMethod.POST)

public String login(HttpServletRequest request){

String resultPageURL = InternalResourceViewResolver.FORWARD_URL_PREFIX + "/";

String username = request.getParameter("username");

String password = request.getParameter("password");

UsernamePasswordToken token = new UsernamePasswordToken(username, password);

token.setRememberMe(true);

System.out.println("为了验证登录用户而封装的token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));

//获取当前的Subject

Subject currentUser = SecurityUtils.getSubject();

try {

//在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查

//每个Realm都能在必要时对提交的AuthenticationTokens作出反应

//所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法

System.out.println("对用户[" + username + "]进行登录验证..验证开始");

currentUser.login(token);

System.out.println("对用户[" + username + "]进行登录验证..验证通过");

resultPageURL = "main";

}catch(UnknownAccountException uae){

System.out.println("对用户[" + username + "]进行登录验证..验证未通过,未知账户");

request.setAttribute("message_login", "未知账户");

}catch(IncorrectCredentialsException ice){

System.out.println("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");

request.setAttribute("message_login", "密码不正确");

}catch(LockedAccountException lae){

System.out.println("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");

request.setAttribute("message_login", "账户已锁定");

}catch(ExcessiveAttemptsException eae){

System.out.println("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");

request.setAttribute("message_login", "用户名或密码错误次数过多");

}catch(AuthenticationException ae){

//通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景

System.out.println("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");

ae.printStackTrace();

request.setAttribute("message_login", "用户名或密码不正确");

}

//验证是否登录成功

if(currentUser.isAuthenticated()){

System.out.println("用户[" + username + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)");

}else{

token.clear();

}

return resultPageURL;

}

/**

* 用户登出

*/

@RequestMapping("/logout")

public String logout(HttpServletRequest request){

SecurityUtils.getSubject().logout();

return InternalResourceViewResolver.REDIRECT_URL_PREFIX + "/";

}

}

6、UserController.java------处理普通用户访问package com.papio.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller  @RequestMapping("mydemo")

public class UserController {

@RequestMapping(value="/getUserInfo")

public String getUserInfo(HttpServletRequest request){

String currentUser = (String)request.getSession().getAttribute("currentUser");

System.out.println("当前登录的用户为[" + currentUser + "]");

request.setAttribute("currUser", currentUser);

return "/user/info";

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值