新手想要看到效果,直接根据步骤一步步复制即可,如有错误可在下方评论。
我这里面使用的是jsp页面,如要使用html可进行后期修改。
它这里想要实现的效果就是,未登录时,跳转登录后要跳转的页面默认是登录页面。
只有在登录后才可以正常访问登录后的页面
首先这是我的目录
ShiroConfig.java
package com.lyh.config;
import com.lyh.shiro.realms.CustomerRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
//用来整合shiro相关的配置
@Configuration
public class ShiroConfig {
//1.创建shiroFilter //负责拦截所有请求
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//给filter设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//配置系统受限资源
//配置系统公共资源
Map<String,String> map = new HashMap<String,String>();
map.put("/user/login","anon");//anon 设置为公共资源 放行资源放在下面
map.put("/user/register","anon");//anon 设置为公共资源 放行资源放在下面
map.put("/register.jsp","anon");//anon 设置为公共资源 放行资源放在下面
map.put("/user/getImage","anon");
map.put("/**","authc");//authc 请求这个资源需要认证和授权
//默认认证界面路径---当认证不通过时跳转
shiroFilterFactoryBean.setLoginUrl("/login.jsp");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//2.创建安全管理器
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//给安全管理器设置
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
}
@Bean
public Realm getRealm(){
CustomerRealm customerRealm = new CustomerRealm();
//设置hashed凭证校验匹配器
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//设置md5加密
credentialsMatcher.setHashAlgorithmName("md5");
//设置散列次数
credentialsMatcher.setHashIterations(1024);
customerRealm.setCredentialsMatcher(credentialsMatcher);
return customerRealm;
}
}
Controller.java
package com.lyh.controller;
import com.lyh.entity.User;
import com.lyh.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
//用户注册
@RequestMapping("register")
public String register(User user){
try {
userService.register(user);
return "redirect:/login.jsp";
} catch (Exception e) {
e.printStackTrace();
return "redirect:/register.jsp";
}
}
//退出登录
@RequestMapping("logout")
public String logout(){
Subject subject=SecurityUtils.getSubject();
subject.logout();//退出登录
return "redirect:/login.jsp";
}
/**
* 用来处理身份认证
* @param username
* @param password
* @return
*/
@RequestMapping("login")
public String login(String username,String password){
//获取主体对象
Subject subject= SecurityUtils.getSubject();
try {
subject.login(new UsernamePasswordToken(username,password));
System.out.println("登录成功");
return "redirect:/index.jsp";
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用户名错误或不存在!!!");
}catch (IncorrectCredentialsException e){
e.printStackTrace();
System.out.println("密码不正确!!!");
}
return "redirect:/login.jsp";
}
}
UserDao.java
package com.lyh.dao;
import com.lyh.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface UserDao {
void save(User user);
//根据身份信息认证
User findByUserName(String username);
}
User.java(实体类)
package com.lyh.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String id;
private String username;
private String password;
private String salt;
}
UserService.java
package com.lyh.service;
import com.lyh.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public interface UserService {
//注册
void register(User user);
//根据用户名查询业务的方法
User findByUserName(String username);
}
UserServiceImpl.java
package com.lyh.service;
import com.lyh.dao.UserDao;
import com.lyh.entity.User;
import com.lyh.utils.SaltUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void register(User user) {
//处理业务调用dao
//1.生成随机盐
String salt= SaltUtils.getSalt(8);
//2.将随机盐保存到数据
user.setSalt(salt);
//3.明文密码进行md5+salt+hash散列
Md5Hash md5Hash=new Md5Hash(user.getPassword(),salt,1024);
user.setPassword(md5Hash.toHex());
userDao.save(user);
}
@Override
public User findByUserName(String username) {
return userDao.findByUserName(username);
}
}
CustomerRealm.java
package com.lyh.shiro.realms;
import com.lyh.entity.User;
import com.lyh.service.UserService;
import com.lyh.utils.ApplicationContextUtils;
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.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.util.ObjectUtils;
//自定义realm
public class CustomerRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//根据身份信息//从传过来的token获取到的用户名
String principal = (String) token.getPrincipal();
//在工厂中获取service对象
UserService userService = (UserService) ApplicationContextUtils.getBean("userService");
//根据身份信息查询
User user = userService.findByUserName(principal);
System.out.println("User:"+user);
//用户不为空
if(!ObjectUtils.isEmpty(user)){
//返回数据库信息
// SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(),
// ByteSource.Util.bytes(user.getSalt()), this.getName());
// return simpleAuthenticationInfo;
return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),ByteSource.Util.bytes(user.getSalt()),this.getName());
}
return null;
}
}
Utils中需要的两个包
ApplicationContextUtils.java
package com.lyh.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
//根据bean名字获取工厂中指定bean 对象
public static Object getBean(String beanName){
// System.out.println("beanName"+beanName);
// Object object=context.getBean(beanName);
// System.out.println("object"+object);
return context.getBean(beanName);
}
}
SaltUtils.java
package com.lyh.utils;
import java.util.Random;
public class SaltUtils {
/**
* 生成salt的静态方法
* @param n
* @return
*/
public static String getSalt(int n){
char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
char aChar = chars[new Random().nextInt(chars.length)];
sb.append(aChar);
}
return sb.toString();
}
// //测试
// public static void main(String[] args) {
// String salt=geSalt(8);
// System.out.println(salt);
// }
}
UserDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lyh.dao.UserDao">
<insert id="save" parameterType="com.lyh.entity.User" useGeneratedKeys="true">
insert into t_user values(#{id},#{username},#{password},#{salt})
</insert>
<select id="findByUserName" parameterType="String" resultType="com.lyh.entity.User">
select id,username,password,salt from t_user
where username = #{username}
</select>
</mapper>
login.jsp
<%@page pageEncoding="utf-8" contentType="text/html; utf-8" isELIgnored="false" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>springboot</title>
</head>
<body>
<h1>登录页面</h1>
<form action="${pageContext.request.contextPath}/user/login" method="post">
用户名: <input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
<input type="submit" value="登录"><a href="register.jsp">点击注册</a>
</form>
</body>
</html>
后面有一个登录后的页面index.jsp,这里就测试一下吧