Maven+ssm+Shiro集成

ok!!!首先要集成一个Maven+ssm

假设我么已经集成好了。

Shiro在这套体系中所需要的组件有:

web.xml中需要配置Shiro过滤器

Spring-shiro.xml中需要进行配置过滤器,SecurityManager,Realm

Springmvc.xml中配置Shiro注解的启用,Shiro的异常统一处理/SpringMVC的异常处理Bean

一:导入Shirojar依赖

pom.xml导入如下坐标

!-- shiro需要的架包 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>1.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-web</artifactId>
			<version>1.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.2.4</version>
		</dependency>

二:配置

目录结构如下

web.xml

<!-- Shiro配置 -->
	<filter>
		<filter-name>shiroFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		<init-param>
			<param-name>targetFilterLifecycle</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>shiroFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>	
	<!--Spring容器的启动 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
        //顺带加载Spring-shiro.xml  
					classpath:applicationContext.xml
					classpath:Spring-shiro.xml
		</param-value>
	</context-param>

spring-shiro.xml

shiro过滤器:

    <!--id需要和web.xml中的过滤器名一致 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- 注入管理器 -->
		<property name="securityManager" ref="securityManager" />
		<!--登录地址,默认为login.jsp-->
		<property name="loginUrl" value="/login" />
		<!--验证报错后,转向的请求地址-->
		<property name="unauthorizedUrl" value="/unauthorized" />
		<!--logout后,请求的地址 -->
		<property name="filters">
			<util:map>
				<entry key="logout" value-ref="logoutFilter" />
			</util:map>
		</property>
		<!-- 权限配置 -->
		<property name="filterChainDefinitions">
			<value>
				<!-- anon  游客,谁都可以
                     authc 需要登录
                     logout 退出,清除缓存
                     以上需要而没有登录的都需要去往login
                     -->
				/login=anon
				/index=anon
				/static/**=anon
				/doLogout=logout
				/** = authc
			</value>
		</property>
	</bean>
	<!-- 退出过滤器 -->
	<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
		<property name="redirectUrl" value="/index" />
	</bean>


	<!-- 安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="databaseRealm" />
		<!--  <property name="sessionManager" ref="sessionManager" />-->
	</bean>
	<!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
	<bean
		class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
		<property name="staticMethod"
			value="org.apache.shiro.SecurityUtils.setSecurityManager" />
		<property name="arguments" ref="securityManager" />
	</bean>

	<bean id="databaseRealm" class="Realm.DatabaseRealm">
    </bean>
    
	<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

springmvc.xml

	<!--启用shiro注解-->
	<bean
		class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
		depends-on="lifecycleBeanPostProcessor">
		<property name="proxyTargetClass" value="true" />
	</bean>
	<bean
		class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager" />
	</bean>
	
	<!-- 控制器异常处理 -->	
    <bean id="exceptionHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
    </bean>
    //自定义的异常处理类
    <bean class="exception.DefaultExceptionHandler"/>

三:流程

四:Controller

4.1我将所有的jsp文件放在WEB-INF/jsp文件下,so

只要localhost:8080/项目名称/index ,就可访问jsp文件夹下的jsp页面

@Controller
@RequestMapping("")
public class pageController {
	   
	@RequestMapping("index")
	public String index(){
		return "index";
	}
	
	@RequiresPermissions("deleteOrder")
	@RequestMapping("deleteOrder")
	public String deleteOrder(){
		return "deleteOrder";
	}
	@RequiresRoles("productManager")
	@RequestMapping("deleteProduct")
	public String deleteProduct(){
		return "deleteProduct";
	}
	@RequestMapping("listProduct")
	public String listProduct(){
		return "listProduct";
	}
	
	@RequestMapping(value="/login",method=RequestMethod.GET)  
	public String login(){
		return "login";
	}
	@RequestMapping("unauthorized")
	public String noPerms(){
		return "unauthorized";
	}

}

4.2userController

@Controller
public class userController {
	@Autowired
	private userService userServiceImpl;
	@RequestMapping(value="/login",method=RequestMethod.POST)
	public String login(String name,String password,Model model) {
		Subject subject = SecurityUtils.getSubject(); 
		//封装信息
        UsernamePasswordToken token = new UsernamePasswordToken(name, password); 
        try { 
        	//进入Realm验证
            subject.login(token);
            Session session=subject.getSession();
            session.setAttribute("subject", subject);
            return "index";
        } catch (AuthenticationException e) { 
        	model.addAttribute("error", "验证失败");
        	return "login";
        } 
	}
	//退出
	@RequestMapping(value="/doLogout")
	public String logout(HttpServletRequest req) {
		SecurityUtils.getSubject().logout();
		return "index";
	}
}

五:Realm

public class DatabaseRealm extends AuthorizingRealm {

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		userService us = (userService) ac.getBean("userServiceImpl");
		// 获取账号密码
		UsernamePasswordToken t = (UsernamePasswordToken) token;
		String userName = token.getPrincipal().toString();
		String password = new String(t.getPassword());
		// 获取数据库中的密码
		String passwordInDB = us.getPassword(userName);
		// 如果为空就是账号不存在,如果不相同就是密码错误,但是都抛出AuthenticationException,而不是抛出具体错误原因,免得给破解者提供帮助信息
		if (null == passwordInDB || !passwordInDB.equals(password)) {
				throw new AuthenticationException();
			}

		// 认证信息里存放账号密码, getName() 是当前Realm的继承方法,通常返回当前类名 :databaseRealm
		SimpleAuthenticationInfo a = new SimpleAuthenticationInfo(userName, password, getName());
		return a;
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		userService us = (userService) ac.getBean("userServiceImpl");
		// 能进入到这里,表示账号已经通过验证了
		String userName = (String) principals.getPrimaryPrincipal();
		// 通过DAO获取角色和权限
		Set<String> permissions = us.listPermissions(userName);
		Set<String> roles = us.listRoles(userName);
		// 授权对象
		SimpleAuthorizationInfo s = new SimpleAuthorizationInfo();
		// 把通过DAO获取到的角色和权限放进去
		s.setStringPermissions(permissions);
		s.setRoles(roles);
		return s;
	}

}

六:异常统一处理

方法有2,Shiro框架与Springmvc都有异常处理的bean

Shiro框架

@ControllerAdvice
public class DefaultExceptionHandler {
    @ExceptionHandler({UnauthorizedException.class})
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ModelAndView processUnauthenticatedException(NativeWebRequest request, UnauthorizedException e) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("ex", e);
        mv.setViewName("unauthorized");
        return mv;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40008535/article/details/83109419
今日推荐