最终效果如下:
工程整体的目录如下:
Java代码如下:
配置文件如下:
页面资源如下:
好了,下面来简单说下过程吧!
准备工作:
先建表:
- drop table if exists user;
- CREATE TABLE `user` (
- `id` int(11) primary key auto_increment,
- `name` varchar(20) NOT NULL,
- `age` int(11) DEFAULT NULL,
- `birthday` date DEFAULT NULL,
- `password` varchar(20) NOT NULL
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- insert into user values(1,'lin',12,'2013-12-01','123456');
- insert into user values(2,'apple',34,'1999-12-01','123456');
- insert into user values(3,'evankaka',23,'2017-12-01','123456');
下面来看看一些代码和配置
1、POM文件
注意不要少导包了,如果项目出现红叉,一般都是JDK版本的设置问题,自己百度一下就可以解决
- 4.0.0
- com.lin
- ShiroLearn1
- war
- 0.0.1-SNAPSHOT
- ShiroLearn1 Maven Webapp
- http://maven.apache.org
- 3.2.8.RELEASE
- 1.6.6
- 1.2.12
- 4.10
- 3.2.1
- org.springframework
- spring-core
- ${spring.version}
- org.springframework
- spring-webmvc
- ${spring.version}
- org.springframework
- spring-context
- ${spring.version}
- org.springframework
- spring-context-support
- ${spring.version}
- org.springframework
- spring-aop
- ${spring.version}
- org.springframework
- spring-aspects
- ${spring.version}
- org.springframework
- spring-tx
- ${spring.version}
- org.springframework
- spring-jdbc
- ${spring.version}
- org.springframework
- spring-web
- ${spring.version}
- junit
- junit
- ${junit.version}
- test
- log4j
- log4j
- ${log4j.version}
- org.slf4j
- slf4j-api
- ${slf4j.version}
- org.slf4j
- slf4j-log4j12
- ${slf4j.version}
- org.springframework
- spring-test
- ${spring.version}
- test
- org.mybatis
- mybatis
- ${mybatis.version}
- org.mybatis
- mybatis-spring
- 1.2.0
- mysql
- mysql-connector-java
- 5.1.29
- javax.servlet
- servlet-api
- 3.0-alpha-1
- org.apache.shiro
- shiro-core
- 1.2.1
- org.apache.shiro
- shiro-web
- 1.2.1
- org.apache.shiro
- shiro-ehcache
- 1.2.1
- org.apache.shiro
- shiro-spring
- 1.2.1
- ShiroLearn1
- maven-war-plugin
- 2.4
- org.apache.maven.plugins
- maven-compiler-plugin
- 2.3.2
- 1.6
- 1.6
2、自定义Shiro拦截器
这里这个拦截器完成了用户名和密码的验证,验证成功后又给用赋角色和权限(注意,这里赋角色和权限我直接写进去了,没有使用数据库,一般都是要通过service层找到用户名后,再去数据库查该用户对应的角色以及权限,然后再加入到shiro中去)
代码如下:
- package com.lin.realm;
- import java.util.HashSet;
- import java.util.Set;
- 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.cache.Cache;
- import org.apache.shiro.realm.AuthorizingRealm;
- import org.apache.shiro.subject.PrincipalCollection;
- import org.apache.shiro.subject.SimplePrincipalCollection;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import com.lin.domain.User;
- import com.lin.service.UserService;
- import com.lin.utils.CipherUtil;
- public class ShiroDbRealm extends AuthorizingRealm {
- private static Logger logger = LoggerFactory.getLogger(ShiroDbRealm.class);
- private static final String ALGORITHM = "MD5";
- @Autowired
- private UserService userService;
- public ShiroDbRealm() {
- super();
- }
- /**
- * 验证登陆
- */
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(
- AuthenticationToken authcToken) throws AuthenticationException {
- UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
- System.out.println(token.getUsername());
- User user = userService.findUserByLoginName(token.getUsername());
- System.out.println(user);
- CipherUtil cipher = new CipherUtil();//MD5加密
- if (user != null) {
- return new SimpleAuthenticationInfo(user.getName(), cipher.generatePassword(user.getPassword()), getName());
- }else{
- throw new AuthenticationException();
- }
- }
- /**
- * 登陆成功之后,进行角色和权限验证
- */
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
- /*这里应该根据userName使用role和permission 的serive层来做判断,并将对应 的权限加进来,下面简化了这一步*/
- Set roleNames = new HashSet();
- Set permissions = new HashSet();
- roleNames.add("admin");//添加角色。对应到index.jsp
- roleNames.add("administrator");
- permissions.add("create");//添加权限,对应到index.jsp
- permissions.add("login.do?main");
- permissions.add("login.do?logout");
- SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
- info.setStringPermissions(permissions);
- return info;
- }
- /**
- * 清除所有用户授权信息缓存.
- */
- public void clearCachedAuthorizationInfo(String principal) {
- SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
- clearCachedAuthorizationInfo(principals);
- }
- /**
- * 清除所有用户授权信息缓存.
- */
- public void clearAllCachedAuthorizationInfo() {
- Cache cache = getAuthorizationCache();
- if (cache != null) {
- for (Object key : cache.keys()) {
- cache.remove(key);
- }
- }
- }
- // @PostConstruct
- // public void initCredentialsMatcher() {//MD5鍔犲瘑
- // HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(ALGORITHM);
- // setCredentialsMatcher(matcher);
- // }
- }
3、shiro的配置文件 :spring-shiro.xml
内容如下:
- Shiro Configuration
- /index.html = authc
- /checkLogin.do = anon
- /login.do = anon
- /logout.html = anon
- /** = authc
这里简要说明下:
(1)
securityManager:这个属性是必须的。 loginUrl:没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面。 successUrl:登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此。 unauthorizedUrl:没有权限默认跳转的页面。
(2)
anon:例子/admins/**=anon 没有参数,表示可以匿名使用。 authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数 roles:例子/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。 perms:例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。 rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。 port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString 是你访问的url里的?后面的参数。 authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证 ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查 注:anon,authcBasic,auchc,user是认证过滤器, perms,roles,ssl,rest,port是授权过滤器
4、web.xml配置解读shiro的配置文件(上面的)
- Archetype Created Web Application
- /login.do
- contextConfigLocation
- classpath:application.xml,classpath:shiro/spring-shiro.xml
- webAppRootKey
- springmvc.root
- SpringEncodingFilter
- org.springframework.web.filter.CharacterEncodingFilter
- encoding
- UTF-8
- forceEncoding
- true
- SpringEncodingFilter
- /*
- shiroFilter
- org.springframework.web.filter.DelegatingFilterProxy
- targetFilterLifecycle
- true
- shiroFilter
- /*
- log4jConfigLocation
- classpath:log4j.properties
- log4jRefreshInterval
- 6000
- org.springframework.web.util.Log4jConfigListener
- org.springframework.web.context.ContextLoaderListener
- org.springframework.web.util.IntrospectorCleanupListener
- dispatcherServlet
- org.springframework.web.servlet.DispatcherServlet
- contextConfigLocation
- classpath:springmvc/spring-mvc.xml
- 1
- dispatcherServlet
- /
- 15
- 404
- /WEB-INF/views/error/404.jsp
- 401
- /WEB-INF/views/error/401.jsp
这里不仅配置了SpringMVC还要配置Shiro!
5、登陆页面login.jsp
以下是默认登陆的界面
- Insert title here
- username:
- password:
6、验证成功页面index.jsp
如果用户名和密码正确后,跳转到的页面
- Shiro登陆实例
- Shiro登陆实例退出
- 一、验证当前用户是否为"访客",即未认证(包含未记住)的用户
- Hi there! Please Login or Signup today!
- 二、认证通过或已记住的用户
- Welcome back John! Not John? Click here to login.
- 三、已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。
- Update your contact information.
- 四、未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。
- Please login in order to update your credit card information.
- 五、输出当前用户信息,通常为登录帐号信息
- Hello, , how are you today?
- 六、验证当前用户是否属于该角色
- Administer the system
- 七、与hasRole标签逻辑相反,当用户不属于该角色时验证通过
- Sorry, you are not allowed to administer the system.
- 八、验证当前用户是否属于以下任意一个角色。
- You are either a developer,manager, or administrator.
- 九、验证当前用户权限。
- 当前用户拥有增加的权限!!!!!!!!!!!!!
- 当前用户拥有删除的权限!!!!!!!!!!!!!
7、controller层来看看
这里/{id}/showUser主要是来验证是否连接成功(现在无法测试了),当然在工程里你也可以到src/test/java里的包com.lin.service下的UserServiceTest.java,那里我也写了一个单元测试的类。
- package com.lin.controller;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authc.UsernamePasswordToken;
- import org.apache.shiro.subject.Subject;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseBody;
- import com.lin.domain.User;
- import com.lin.realm.ShiroDbRealm;
- import com.lin.service.UserService;
- import com.lin.utils.CipherUtil;
- @Controller
- public class UserControler {
- private static Logger logger = LoggerFactory.getLogger(ShiroDbRealm.class);
- @Autowired
- private UserService userService;
- /**
- * 验证springmvc与batis连接成功
- * @param id
- * @param request
- * @return
- */
- @RequestMapping("/{id}/showUser")
- public String showUser(@PathVariable int id, HttpServletRequest request) {
- User user = userService.getUserById(id);
- System.out.println(user.getName());
- request.setAttribute("user", user);
- return "showUser";
- }
- /**
- * 初始登陆界面
- * @param request
- * @return
- */
- @RequestMapping("/login.do")
- public String tologin(HttpServletRequest request, HttpServletResponse response, Model model){
- logger.debug("来自IP[" + request.getRemoteHost() + "]的访问");
- return "login";
- }
- /**
- * 验证用户名和密码
- * @param request
- * @return
- */
- @RequestMapping("/checkLogin.do")
- public String login(HttpServletRequest request) {
- String result = "login.do";
- // 取得用户名
- String username = request.getParameter("username");
- //取得 密码,并用MD5加密
- String password = CipherUtil.generatePassword(request.getParameter("password"));
- //String password = request.getParameter("password");
- UsernamePasswordToken token = new UsernamePasswordToken(username, password);
- Subject currentUser = SecurityUtils.getSubject();
- try {
- System.out.println("----------------------------");
- if (!currentUser.isAuthenticated()){//使用shiro来验证
- token.setRememberMe(true);
- currentUser.login(token);//验证角色和权限
- }
- System.out.println("result: " + result);
- result = "index";//验证成功
- } catch (Exception e) {
- logger.error(e.getMessage());
- result = "login。do";//验证失败
- }
- return result;
- }
- /**
- * 退出
- * @return
- */
- @RequestMapping(value = "/logout")
- @ResponseBody
- public String logout() {
- Subject currentUser = SecurityUtils.getSubject();
- String result = "logout";
- currentUser.logout();
- return result;
- }
- }